diff --git a/.backportrc.json b/.backportrc.json index c56c10290e28d..30b18b7561eaa 100644 --- a/.backportrc.json +++ b/.backportrc.json @@ -1,5 +1,5 @@ { "upstream": "elastic/kibana", - "branches": [{ "name": "7.x", "checked": true }, "7.3", "7.2", "7.1", "7.0", "6.8", "6.7", "6.6", "6.5", "6.4", "6.3", "6.2", "6.1", "6.0", "5.6"], + "branches": [{ "name": "7.x", "checked": true }, "7.4", "7.3", "7.2", "7.1", "7.0", "6.8", "6.7", "6.6", "6.5", "6.4", "6.3", "6.2", "6.1", "6.0", "5.6"], "labels": ["backport"] } diff --git a/.ci/jobs.yml b/.ci/jobs.yml index 89fce3cf488d5..fe28ae79268de 100644 --- a/.ci/jobs.yml +++ b/.ci/jobs.yml @@ -1,34 +1,21 @@ JOB: - - kibana-intake - - x-pack-intake - - kibana-firefoxSmoke + - intake + - firefoxSmoke - kibana-ciGroup1 - kibana-ciGroup2 - kibana-ciGroup3 - kibana-ciGroup4 - kibana-ciGroup5 - kibana-ciGroup6 - - kibana-ciGroup7 - - kibana-ciGroup8 - - kibana-ciGroup9 - - kibana-ciGroup10 - - kibana-ciGroup11 - - kibana-ciGroup12 - - kibana-visualRegression + # - kibana-visualRegression # make sure all x-pack-ciGroups are listed in test/scripts/jenkins_xpack_ci_group.sh - - x-pack-firefoxSmoke - x-pack-ciGroup1 - x-pack-ciGroup2 - x-pack-ciGroup3 - x-pack-ciGroup4 - x-pack-ciGroup5 - - x-pack-ciGroup6 - - x-pack-ciGroup7 - - x-pack-ciGroup8 - - x-pack-ciGroup9 - - x-pack-ciGroup10 - - x-pack-visualRegression + # - x-pack-visualRegression # `~` is yaml for `null` -exclude: ~ +exclude: ~ \ No newline at end of file diff --git a/.ci/run.sh b/.ci/run.sh index 88ce0bd9986a1..e5c26c48546f7 100755 --- a/.ci/run.sh +++ b/.ci/run.sh @@ -11,7 +11,7 @@ source src/dev/ci_setup/setup.sh source src/dev/ci_setup/checkout_sibling_es.sh case "$JOB" in -kibana-intake) +intake) ./test/scripts/jenkins_unit.sh ;; kibana-ciGroup*) @@ -21,12 +21,9 @@ kibana-ciGroup*) kibana-visualRegression*) ./test/scripts/jenkins_visual_regression.sh ;; -kibana-firefoxSmoke*) +firefoxSmoke*) ./test/scripts/jenkins_firefox_smoke.sh ;; -x-pack-intake) - ./test/scripts/jenkins_xpack.sh - ;; x-pack-ciGroup*) export CI_GROUP="${JOB##x-pack-ciGroup}" ./test/scripts/jenkins_xpack_ci_group.sh @@ -34,9 +31,6 @@ x-pack-ciGroup*) x-pack-visualRegression*) ./test/scripts/jenkins_xpack_visual_regression.sh ;; -x-pack-firefoxSmoke*) - ./test/scripts/jenkins_xpack_firefox_smoke.sh - ;; *) echo "JOB '$JOB' is not implemented." exit 1 diff --git a/.eslintignore b/.eslintignore index 12a3f68486047..1219c51b015d0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,7 +5,6 @@ bower_components /target /.es /plugins -/optimize /built_assets /html_docs /src/fixtures/vislib/mock_data diff --git a/.eslintrc.js b/.eslintrc.js index 3f5623f9e9e47..63f30b427e162 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -31,7 +31,9 @@ const ELASTIC_LICENSE_HEADER = ` `; module.exports = { - extends: ['@elastic/eslint-config-kibana'], + root: true, + + extends: ['@elastic/eslint-config-kibana', 'plugin:@elastic/eui/recommended'], overrides: [ /** @@ -160,6 +162,8 @@ module.exports = { { from: ['src/legacy/ui/**/*', 'ui/**/*'], 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/**/server/np_ready/**/*', 'x-pack/legacy/plugins/**/public/np_ready/**/*', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3abc37a5f60b6..e7d6e8001f1de 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,6 +5,7 @@ # App Architecture /src/plugins/data/ @elastic/kibana-app-arch /src/plugins/kibana_utils/ @elastic/kibana-app-arch +/src/plugins/kibana_react/ @elastic/kibana-app-arch # APM /x-pack/legacy/plugins/apm/ @elastic/apm-ui @@ -37,6 +38,7 @@ /src/legacy/server/saved_objects/ @elastic/kibana-platform /src/legacy/ui/public/saved_objects @elastic/kibana-platform /config/kibana.yml @elastic/kibana-platform +/x-pack/plugins/features/ @elastic/kibana-platform # Security /x-pack/legacy/plugins/security/ @elastic/kibana-security diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000000..8a776a909cd9e --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,12 @@ +'Team:AppArch': +- src/plugins/data/**/* +- src/plugins/embeddable/**/* +- src/plugins/kibana_react/**/* +- src/plugins/kibana_utils/**/* +- src/legacy/core_plugins/dashboard_embeddable_container/**/* +- src/legacy/core_plugins/data/**/* +- src/legacy/core_plugins/embeddable_api/**/* +- src/legacy/core_plugins/interpreter/**/* +- src/legacy/ui/public/index_patterns/**/* +- src/legacy/ui/public/indexed_array/**/* +- src/legacy/ui/public/new_platform/**/* diff --git a/.i18nrc.json b/.i18nrc.json index 292f4d7e9c108..a589b14dfc7ee 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -2,6 +2,7 @@ "paths": { "common.ui": "src/legacy/ui", "data": "src/legacy/core_plugins/data", + "expressions": "src/legacy/core_plugins/expressions", "kibana_react": "src/legacy/core_plugins/kibana_react", "server": "src/legacy/server", "console": "src/legacy/core_plugins/console", @@ -23,9 +24,11 @@ "tileMap": "src/legacy/core_plugins/tile_map", "timelion": "src/legacy/core_plugins/timelion", "visTypeTagCloud": "src/legacy/core_plugins/vis_type_tagcloud", - "tsvb": "src/legacy/core_plugins/metrics", + "visTypeTimeseries": "src/legacy/core_plugins/vis_type_timeseries", "kbnESQuery": "packages/kbn-es-query", - "inspector": "src/plugins/inspector" + "inspector": "src/plugins/inspector", + "kibana-react": "src/plugins/kibana_react", + "esUi": "src/plugins/es_ui_shared" }, "exclude": ["src/legacy/ui/ui_render/ui_render_mixin.js"], "translations": [] diff --git a/.sass-lint.yml b/.sass-lint.yml index 18ce54048d7db..f5abc1af9735c 100644 --- a/.sass-lint.yml +++ b/.sass-lint.yml @@ -6,32 +6,28 @@ files: - 'src/legacy/ui/public/vislib/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/rollup/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/security/**/*.s+(a|c)ss' + - 'x-pack/legacy/plugins/canvas/**/*.s+(a|c)ss' rules: quotes: - 2 - - - style: 'single' + - style: 'single' # } else { style on one line, like our JS brace-style: - 2 - - - style: '1tbs' + - style: '1tbs' variable-name-format: - 2 - - - convention: 'camelcase' + - convention: 'camelcase' # Needs regex, right now we ignore class-name-format: 0 # Order how you please property-sort-order: 0 hex-notation: - 2 - - - style: 'uppercase' + - style: 'uppercase' mixin-name-format: - 2 - - - allow-leading-underscore: false + - allow-leading-underscore: false convention: 'camelcase' # Use none instead of 0 for no border border-zero: @@ -46,8 +42,7 @@ rules: indentation: 2 function-name-format: - 2 - - - allow-leading-underscore: false + - allow-leading-underscore: false convention: 'camelcase' # This removes the need for ::hover pseudo-element: 0 @@ -61,23 +56,20 @@ rules: force-attribute-nesting: 0 no-qualifying-elements: - 2 - - - # Allows input[type=search] + - # Allows input[type=search] allow-element-with-attribute: 1 # Files can end without a newline final-newline: 0 # We use some rare duplicate property values for browser variance no-duplicate-properties: - 2 - - - exclude: + - exclude: - 'font-size' - 'word-break' # Put a line-break between sections of CSS, but allow quicky one-liners for legibility empty-line-between-blocks: - 2 - - - allow-single-line-rulesets: 1 + - allow-single-line-rulesets: 1 # Warns are nice for deprecations and development no-warn: 0 # Transition all is useful in certain situations and there's no recent info to suggest slowdown diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000000..996406928021d --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,264 @@ +#!/bin/groovy + +stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a little bit + timeout(time: 180, unit: 'MINUTES') { + timestamps { + ansiColor('xterm') { + catchError { + parallel([ + 'intake-agent': legacyJobRunner('intake'), + 'firefox-smoke-agent': legacyJobRunner('firefoxSmoke'), + 'kibana-oss-agent': withWorkers('kibana-oss-tests', { buildOss() }, [ + 'oss-ciGroup1': getOssCiGroupWorker(1), + 'oss-ciGroup2': getOssCiGroupWorker(2), + 'oss-ciGroup3': getOssCiGroupWorker(3), + 'oss-ciGroup4': getOssCiGroupWorker(4), + 'oss-ciGroup5': getOssCiGroupWorker(5), + 'oss-ciGroup6': getOssCiGroupWorker(6), + // 'oss-ciGroup7': getOssCiGroupWorker(7), + // 'oss-ciGroup8': getOssCiGroupWorker(8), + // 'oss-ciGroup9': getOssCiGroupWorker(9), + // 'oss-ciGroup10': getOssCiGroupWorker(10), + // 'oss-ciGroup11': getOssCiGroupWorker(11), + // 'oss-ciGroup12': getOssCiGroupWorker(12), + // 'oss-visualRegression': getPostBuildWorker('visualRegression', { runbld './test/scripts/jenkins_visual_regression.sh' }), + // 'oss-firefoxSmoke': getPostBuildWorker('firefoxSmoke', { runbld './test/scripts/jenkins_firefox_smoke.sh' }), + ]), + 'kibana-xpack-agent': withWorkers('kibana-xpack-tests', { buildXpack() }, [ + 'xpack-ciGroup1': getXpackCiGroupWorker(1), + 'xpack-ciGroup2': getXpackCiGroupWorker(2), + 'xpack-ciGroup3': getXpackCiGroupWorker(3), + 'xpack-ciGroup4': getXpackCiGroupWorker(4), + 'xpack-ciGroup5': getXpackCiGroupWorker(5), + // 'xpack-ciGroup6': getXpackCiGroupWorker(6), + // 'xpack-ciGroup7': getXpackCiGroupWorker(7), + // 'xpack-ciGroup8': getXpackCiGroupWorker(8), + // 'xpack-ciGroup9': getXpackCiGroupWorker(9), + // 'xpack-ciGroup10': getXpackCiGroupWorker(10), + // 'xpack-firefoxSmoke': getPostBuildWorker('xpack-firefoxSmoke', { runbld './test/scripts/jenkins_xpack_firefox_smoke.sh' }), + // 'xpack-visualRegression': getPostBuildWorker('xpack-visualRegression', { runbld './test/scripts/jenkins_xpack_visual_regression.sh' }), + ]), + ]) + } + node('flyweight') { + sendMail() + } + } + } + } +} + +def withWorkers(name, preWorkerClosure = {}, workerClosures = [:]) { + return { + jobRunner('tests-xl') { + try { + doSetup() + preWorkerClosure() + + def nextWorker = 1 + def worker = { workerClosure -> + def workerNumber = nextWorker + nextWorker++ + + return { + workerClosure(workerNumber) + } + } + + def workers = [:] + workerClosures.each { workerName, workerClosure -> + workers[workerName] = worker(workerClosure) + } + + parallel(workers) + } finally { + catchError { + uploadAllGcsArtifacts(name) + } + + catchError { + publishJunit() + } + } + } + } +} + +def getPostBuildWorker(name, closure) { + return { workerNumber -> + def kibanaPort = "61${workerNumber}1" + def esPort = "61${workerNumber}2" + def esTransportPort = "61${workerNumber}3" + + withEnv([ + "CI_WORKER_NUMBER=${workerNumber}", + "TEST_KIBANA_HOST=localhost", + "TEST_KIBANA_PORT=${kibanaPort}", + "TEST_KIBANA_URL=http://elastic:changeme@localhost:${kibanaPort}", + "TEST_ES_URL=http://elastic:changeme@localhost:${esPort}", + "TEST_ES_TRANSPORT_PORT=${esTransportPort}", + "IS_PIPELINE_JOB=1", + ]) { + closure() + } + } +} + +def getOssCiGroupWorker(ciGroup) { + return getPostBuildWorker("ciGroup" + ciGroup, { + withEnv([ + "CI_GROUP=${ciGroup}", + "JOB=kibana-ciGroup${ciGroup}", + ]) { + runbld "./test/scripts/jenkins_ci_group.sh" + } + }) +} + +def getXpackCiGroupWorker(ciGroup) { + return getPostBuildWorker("xpack-ciGroup" + ciGroup, { + withEnv([ + "CI_GROUP=${ciGroup}", + "JOB=xpack-kibana-ciGroup${ciGroup}", + ]) { + runbld "./test/scripts/jenkins_xpack_ci_group.sh" + } + }) +} + +def legacyJobRunner(name) { + return { + parallel([ + "${name}": { + withEnv([ + "JOB=${name}", + ]) { + jobRunner('linux && immutable') { + try { + runbld '.ci/run.sh' + } finally { + catchError { + uploadAllGcsArtifacts(name) + } + catchError { + publishJunit() + } + } + } + } + } + ]) + } +} + +def jobRunner(label, closure) { + node(label) { + def scmVars = checkout scm + + withEnv([ + "CI=true", + "HOME=${env.JENKINS_HOME}", + "PR_SOURCE_BRANCH=${env.ghprbSourceBranch}", + "PR_TARGET_BRANCH=${env.ghprbTargetBranch}", + "PR_AUTHOR=${env.ghprbPullAuthorLogin}", + "TEST_BROWSER_HEADLESS=1", + "GIT_BRANCH=${scmVars.GIT_BRANCH}", + ]) { + withCredentials([ + string(credentialsId: 'vault-addr', variable: 'VAULT_ADDR'), + string(credentialsId: 'vault-role-id', variable: 'VAULT_ROLE_ID'), + string(credentialsId: 'vault-secret-id', variable: 'VAULT_SECRET_ID'), + ]) { + // scm is configured to check out to the ./kibana directory + dir('kibana') { + closure() + } + } + } + } +} + +// TODO what should happen if GCS, Junit, or email publishing fails? Unstable build? Failed build? + +def uploadGcsArtifact(workerName, pattern) { + def storageLocation = "gs://kibana-ci-artifacts/jobs/${env.JOB_NAME}/${BUILD_NUMBER}/${workerName}" // TODO + // def storageLocation = "gs://kibana-pipeline-testing/jobs/pipeline-test/${BUILD_NUMBER}/${workerName}" + + googleStorageUpload( + credentialsId: 'kibana-ci-gcs-plugin', + bucket: storageLocation, + pattern: pattern, + sharedPublicly: true, + showInline: true, + ) +} + +def uploadAllGcsArtifacts(workerName) { + def ARTIFACT_PATTERNS = [ + 'target/kibana-*', + 'target/junit/**/*', + 'test/**/screenshots/**/*.png', + 'test/functional/failure_debug/html/*.html', + 'x-pack/test/**/screenshots/**/*.png', + 'x-pack/test/functional/failure_debug/html/*.html', + 'x-pack/test/functional/apps/reporting/reports/session/*.pdf', + ] + + ARTIFACT_PATTERNS.each { pattern -> + uploadGcsArtifact(workerName, pattern) + } +} + +def publishJunit() { + junit(testResults: 'target/junit/**/*.xml', allowEmptyResults: true, keepLongStdio: true) +} + +def sendMail() { + sendInfraMail() + sendKibanaMail() +} + +def sendInfraMail() { + catchError { + step([ + $class: 'Mailer', + notifyEveryUnstableBuild: true, + recipients: 'infra-root+build@elastic.co', + sendToIndividuals: false + ]) + } +} + +def sendKibanaMail() { + catchError { + if(params.NOTIFY_ON_FAILURE && currentBuild.result != 'SUCCESS' && currentBuild.result != 'ABORTED') { + emailext( + // to: 'build-kibana@elastic.co', + to: 'brian.seeders@elastic.co', // TODO switch this out after testing + subject: "${env.PROJECT_NAME} - Build # ${env.BUILD_NUMBER} - ${currentBuild.result}", + body: '${SCRIPT,template="groovy-html.template"}', + mimeType: 'text/html', + ) + } + } +} + +def runbld(script) { + sh '#!/usr/local/bin/runbld\n' + script +} + +def bash(script) { + sh "#!/bin/bash -x\n${script}" +} + +def doSetup() { + runbld "./test/scripts/jenkins_setup.sh" +} + +def buildOss() { + runbld "./test/scripts/jenkins_build_kibana.sh" +} + +def buildXpack() { + runbld "./test/scripts/jenkins_xpack_build_kibana.sh" +} diff --git a/bin/kibana b/bin/kibana index 39c61808bbc07..558facb9da32b 100755 --- a/bin/kibana +++ b/bin/kibana @@ -21,4 +21,4 @@ if [ ! -x "$NODE" ]; then exit 1 fi -NODE_ENV=production exec "${NODE}" --no-warnings --max-http-header-size=65536 $NODE_OPTIONS "${DIR}/src/cli" ${@} +NODE_OPTIONS="--no-warnings --max-http-header-size=65536 ${NODE_OPTIONS}" NODE_ENV=production exec "${NODE}" "${DIR}/src/cli" ${@} diff --git a/bin/kibana-plugin b/bin/kibana-plugin index 8b9ae268c2536..b843d4966c6d1 100755 --- a/bin/kibana-plugin +++ b/bin/kibana-plugin @@ -21,4 +21,4 @@ if [ ! -x "$NODE" ]; then exit 1 fi -NODE_ENV=production exec "${NODE}" $NODE_OPTIONS --no-warnings "${DIR}/src/cli_plugin" "$@" +NODE_OPTIONS="--no-warnings ${NODE_OPTIONS}" NODE_ENV=production exec "${NODE}" "${DIR}/src/cli_plugin" "$@" diff --git a/bin/kibana-plugin.bat b/bin/kibana-plugin.bat index 5a0ae70760ca1..bf382a0657ade 100755 --- a/bin/kibana-plugin.bat +++ b/bin/kibana-plugin.bat @@ -14,7 +14,8 @@ If Not Exist "%NODE%" ( ) TITLE Kibana Server -"%NODE%" %NODE_OPTIONS% --no-warnings "%DIR%\src\cli_plugin" %* + +set "NODE_OPTIONS=--no-warnings %NODE_OPTIONS%" && "%NODE%" "%DIR%\src\cli_plugin" %* :finally diff --git a/bin/kibana.bat b/bin/kibana.bat index e4e6dfb4776a4..9d8ba359e53af 100755 --- a/bin/kibana.bat +++ b/bin/kibana.bat @@ -14,7 +14,7 @@ If Not Exist "%NODE%" ( Exit /B 1 ) -"%NODE%" --no-warnings --max-http-header-size=65536 %NODE_OPTIONS% "%DIR%\src\cli" %* +set "NODE_OPTIONS=--no-warnings --max-http-header-size=65536 %NODE_OPTIONS%" && "%NODE%" "%DIR%\src\cli" %* :finally diff --git a/docs/api.asciidoc b/docs/api.asciidoc deleted file mode 100644 index db584ac544fac..0000000000000 --- a/docs/api.asciidoc +++ /dev/null @@ -1,48 +0,0 @@ -[[api]] -= REST API - -[partintro] --- -Some of the features of Kibana are provided via a REST API, which is ideal for -people that want to create an integration with Kibana or that want to automate -certain aspects of configuring and deploying Kibana. - -Each API in this documentation should be clearly marked as either `stable`, -`beta`, or `experimental`. If an API is not marked, it should be considered -`experimental`. - -What do these labels mean? - -* *Stable* APIs should be safe to use extensively in production. Any breaking -changes to these APIs should only occur in major versions and will be -clearly documented in the breaking changes documentation for that release. -* *Beta* APIs are on track to become stable, permanent features of Kibana. -Caution should be exercised in their use since it is possible we'd have to make -a breaking change to these APIs in a minor version, but we'll avoid this -wherever possible. -* *Experimental* APIs are just that - an experiment. An experimental API might -have breaking changes in any version of Kibana, or it might even be removed -entirely. - -NOTE: You cannot access these APIs via the Console in Kibana. - -[float] -== APIs -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> --- - -include::api/features.asciidoc[] -include::api/spaces-management.asciidoc[] -include::api/role-management.asciidoc[] -include::api/saved-objects.asciidoc[] -include::api/dashboard-import.asciidoc[] -include::api/logstash-configuration-management.asciidoc[] -include::api/url-shortening.asciidoc[] -include::api/upgrade-assistant.asciidoc[] diff --git a/docs/api/dashboard-import.asciidoc b/docs/api/dashboard-import.asciidoc index b928abfd06881..19eb6f2a446b5 100644 --- a/docs/api/dashboard-import.asciidoc +++ b/docs/api/dashboard-import.asciidoc @@ -1,19 +1,14 @@ [[dashboard-import-api]] -== Dashboard Import API +== Dashboard import and export APIs -The dashboard import/export APIs allow people to import dashboards along with -all of their corresponding saved objects such as visualizations, saved +Import and export dashboards with the corresponding saved objects, such as visualizations, saved searches, and index patterns. -Traditionally, developers would perform this level of integration by writing -documents directly to the `.kibana` index. *Do not do this!* Writing directly -to the `.kibana` index is not safe and it _will_ result in corrupted data that -permanently breaks Kibana in a future version. +WARNING: Do not write documents directly to the `.kibana` index. When you write directly +to the `.kibana` index, the data becomes corrupted and permanently breaks future {kib} versions. -NOTE: You cannot access these endpoints via the Console in Kibana. - -* <> -* <> +* <> +* <> include::dashboard-import/import.asciidoc[] include::dashboard-import/export.asciidoc[] diff --git a/docs/api/dashboard-import/export.asciidoc b/docs/api/dashboard-import/export.asciidoc index e71631aefd340..74753f75a3557 100644 --- a/docs/api/dashboard-import/export.asciidoc +++ b/docs/api/dashboard-import/export.asciidoc @@ -1,40 +1,44 @@ -[[dashboard-import-api-export]] -=== Export Dashboard +[[dashboard-api-export]] +=== Export dashboard API +++++ +Dashboard export +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The dashboard export API allows people to export dashboards along with all of -their corresponding saved objects such as visualizations, saved searches, and -index patterns. +Export dashboards and corresponding saved objects. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[dashboard-api-export-request]] ==== Request `GET /api/kibana/dashboards/export` -==== Query Parameters +[[dashboard-api-export-params]] +==== Query parameters -`dashboard` (required):: - (array|string) The id(s) of the dashboard(s) to export +`dashboard`:: + (Required, array|string) The IDs of the dashboards that you want to export. +[[dashboard-api-export-response-body]] ==== Response body -The response body will have a top level `objects` property that contains an -array of saved objects. The order of these objects is not guaranteed. You -should use this exact response body as the request body for the corresponding -<>. +`objects`:: + (array) A top level property that includes the saved objects. The order of the objects is not guaranteed. Use the exact response body as the request body for the corresponding <>. + +[[dashboard-api-export-codes]] +==== Response code -==== Examples +`200`:: + Indicates a successful call. -The following example exports all saved objects associated with and including -the dashboard with id `942dcef0-b2cd-11e8-ad8e-85441f0c2e5c`. +[float] +[[dashboard-api-export-example]] +==== Example [source,js] -------------------------------------------------- -GET api/kibana/dashboards/export?dashboard=942dcef0-b2cd-11e8-ad8e-85441f0c2e5c +GET api/kibana/dashboards/export?dashboard=942dcef0-b2cd-11e8-ad8e-85441f0c2e5c <1> -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` along with the exported -objects as the response body. +<1> In this example, `942dcef0-b2cd-11e8-ad8e-85441f0c2e5c` is the dashboard ID. diff --git a/docs/api/dashboard-import/import.asciidoc b/docs/api/dashboard-import/import.asciidoc index 9e6752a8ee41b..863de5f0cfa04 100644 --- a/docs/api/dashboard-import/import.asciidoc +++ b/docs/api/dashboard-import/import.asciidoc @@ -1,41 +1,46 @@ [[dashboard-import-api-import]] -=== Import Dashboard +=== Import dashboard API +++++ +Import dashboard +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The dashboard import API allows people to import dashboards along with all of -their corresponding saved objects such as visualizations, saved searches, and -index patterns. +Import dashboards and corresponding saved objects. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[dashboard-api-import-request]] ==== Request `POST /api/kibana/dashboards/import` -==== Query Parameters +[[dashboard-api-import-params]] +==== Query parameters -`force` (optional):: - (boolean) Overwrite any existing objects on id conflict -`exclude` (optional):: - (array) Saved object types that should not be imported +`force`:: + (Optional, boolean) Overwrite any existing objects on ID conflict. + +`exclude`:: + (Optional, array) Saved object types that you want to exclude from the import. -==== Request Body +[[dashboard-api-import-request-body]] +==== Request body -The request body is JSON, but you should not manually construct a payload to -this endpoint. Instead, use the complete response body from the -<> as the request body to -this import API. +Use the complete response body from the <> as the request body. Do not manually construct a payload to the endpoint. +[[dashboard-api-import-response-body]] ==== Response body -The response body will have a top level `objects` property that contains an -array of the saved objects that were created. +`objects`:: + (array) A top level property that includes the saved objects. -==== Examples +[[dashboard-api-import-codes]] +==== Response code -The following example imports saved objects associated with and including the -dashboard with id `942dcef0-b2cd-11e8-ad8e-85441f0c2e5c`. +`200`:: + Indicates a successful call, even if there are errors importing individual saved objects. If there ar errors, the error information is returned in the response body on an object-by-object basis. + +[[dashboard-api-import-example]] +==== Example [source,js] -------------------------------------------------- @@ -92,7 +97,3 @@ POST api/kibana/dashboards/import?exclude=index-pattern } -------------------------------------------------- // KIBANA - -A response code of `200` will be returned even if there are errors importing -individual saved objects. In that case, error information will be returned in -the response body on an object-by-object basis. diff --git a/docs/api/features.asciidoc b/docs/api/features.asciidoc index e986157d10109..798f2be3d7212 100644 --- a/docs/api/features.asciidoc +++ b/docs/api/features.asciidoc @@ -2,12 +2,8 @@ [[features-api]] == Features API -experimental[This API is *experimental* and may be changed or removed completely in a future release.] +View information about the available features in {kib}. Features are used by spaces and security to refine and secure access to {kib}. -The features API allows you to view information about available features in {kib}. Features are used by spaces and security to refine and secure access to {kib}. - -NOTE: You cannot access these endpoints via the Console in {kib}. - -* <> +* <> include::features/get.asciidoc[] diff --git a/docs/api/features/get.asciidoc b/docs/api/features/get.asciidoc index eb18d2cb57c22..c4e4ff182448f 100644 --- a/docs/api/features/get.asciidoc +++ b/docs/api/features/get.asciidoc @@ -1,29 +1,28 @@ [[features-api-get]] -=== Get Features - -experimental[This API is *experimental* and may be changed or removed completely in a future release.] +=== Get features API +++++ +Get features +++++ Retrieves all {kib} features. -Note: You cannot access this endpoint via the Console in {kib}. +experimental[This API is *experimental* and may be changed or removed completely in a future release.] -==== Get all {kib} features +[[features-api-get-request]] +==== Request -===== Request +`GET /api/features` -To retrieve all features, issue a GET request to the -/api/features/v1 endpoint. +[[features-api-get-codes]] +==== Response code -[source,js] --------------------------------------------------- -GET /api/features/v1 --------------------------------------------------- -// KIBANA +`200`:: + Indicates a successful call. -===== Response +[[features-api-get-example]] +==== Example -A successful call returns a response code of `200` and a response body containing a JSON -representation of the features. +The API returns the following: [source,js] -------------------------------------------------- diff --git a/docs/api/logstash-configuration-management.asciidoc b/docs/api/logstash-configuration-management.asciidoc index 78cb215723eba..e53218ec439aa 100644 --- a/docs/api/logstash-configuration-management.asciidoc +++ b/docs/api/logstash-configuration-management.asciidoc @@ -1,20 +1,15 @@ [role="xpack"] [[logstash-configuration-management-api]] -== Logstash Configuration Management API +== Logstash configuration management APIs -The Logstash configuration management API allows users to programmatically integrate with the -Logstash configuration management feature. +Programmatically integrate with the Logstash configuration management feature. -Traditionally users would perform this integration by accessing the the `.logstash` index -directly. *Do not do this!* The structure of this index is subject to change, which could -cause your integration to break. Instead, use the following API. +WARNING: Do not directly access the `.logstash` index. The structure of the `.logstash` index is subject to change, which could cause your integration to break. Instead, use the Logstash configuration management APIs. -NOTE: You cannot access these endpoints via the Console in Kibana. - -* <> -* <> -* <> -* <> +* <> +* <> +* <> +* <> include::logstash-configuration-management/create.asciidoc[] include::logstash-configuration-management/retrieve.asciidoc[] diff --git a/docs/api/logstash-configuration-management/create.asciidoc b/docs/api/logstash-configuration-management/create.asciidoc index 72372d3f6185b..bc4869f8cf6bf 100644 --- a/docs/api/logstash-configuration-management/create.asciidoc +++ b/docs/api/logstash-configuration-management/create.asciidoc @@ -1,41 +1,46 @@ [role="xpack"] [[logstash-configuration-management-api-create]] -=== Create Pipeline +=== Create Logstash pipeline API +++++ +Create pipeline +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The Create Pipeline API enables you to create a centrally-managed Logstash pipeline. You can also use -it to update an existing pipeline. +Create a centrally-managed Logstash pipeline, or update an existing pipeline. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] -[float] +[[logstash-configuration-management-api-create-request]] ==== Request `PUT /api/logstash/pipeline/` -[float] -==== Path Parameters +[[logstash-configuration-management-api-create-params]] +==== Path parameters -`id` (required):: - (string) ID for pipeline. Only alphanumeric characters, hyphens, and underscores may be used. +`id`:: + (Required, string) The pipeline ID. Only alphanumeric characters, hyphens, and underscores are supported. +[[logstash-configuration-management-api-create-request-body]] +==== Request body -[float] -==== Request Body +`description`:: + (Optional, string) The pipeline description. -`description` (optional):: - (string) Description for the pipeline +`pipeline`:: + (Required, string) The pipeline definition. -`pipeline` (required):: - (string) Pipeline definition +`settings`:: + (Optional, object) The pipeline settings. Supported settings, represented as object keys, are `pipeline.workers`, `pipeline.batch.size`, `pipeline.batch.delay`, `queue.type`, `queue.max_bytes`, and `queue.checkpoint.writes`. -`settings` (optional):: - (object) Pipeline settings. Supported settings, represented as object keys, are `pipeline.workers`, `pipeline.batch.size`, `pipeline.batch.delay`, `queue.type`, `queue.max_bytes`, and `queue.checkpoint.writes` +[[logstash-configuration-management-api-create-codes]] +==== Response code +`204 No Content`:: + Indicates a successful call. [float] -==== Examples +[[logstash-configuration-management-api-create-example]] +==== Example [source,js] -------------------------------------------------- @@ -48,5 +53,3 @@ PUT api/logstash/pipeline/hello-world } -------------------------------------------------- // KIBANA - -A successful call returns an HTTP `204 No Content` response. diff --git a/docs/api/logstash-configuration-management/delete.asciidoc b/docs/api/logstash-configuration-management/delete.asciidoc index 36c7060e96a0e..89da16140cb89 100644 --- a/docs/api/logstash-configuration-management/delete.asciidoc +++ b/docs/api/logstash-configuration-management/delete.asciidoc @@ -1,32 +1,36 @@ [role="xpack"] [[logstash-configuration-management-api-delete]] -=== Delete Pipeline +=== Delete Logstash pipeline API +++++ +Delete pipeline +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The Delete Pipeline API enables you to delete a centrally-managed Logstash pipeline. +Delete a centrally-managed Logstash pipeline. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] -[float] +[[logstash-configuration-management-api-delete-request]] ==== Request `DELETE /api/logstash/pipeline/` -[float] -==== Path Parameters +[[logstash-configuration-management-api-delete-params]] +==== Path parameters -`id` (required):: - (string) ID for pipeline. +`id`:: + (Required, string) The pipeline ID. +[[logstash-configuration-management-api-delete-codes]] +==== Response code -[float] -==== Examples +`204 No Content`:: + Indicates a successful call. + +[[logstash-configuration-management-api-delete-example]] +==== Example [source,js] -------------------------------------------------- DELETE api/logstash/pipeline/hello-world -------------------------------------------------- -// KIBANA - -A successful call returns an HTTP `204 No Content` response. \ No newline at end of file +// KIBANA \ No newline at end of file diff --git a/docs/api/logstash-configuration-management/list.asciidoc b/docs/api/logstash-configuration-management/list.asciidoc index d93e734bbdfd4..60532e6dcd7ec 100644 --- a/docs/api/logstash-configuration-management/list.asciidoc +++ b/docs/api/logstash-configuration-management/list.asciidoc @@ -1,28 +1,23 @@ [role="xpack"] [[logstash-configuration-management-api-list]] -=== List Pipelines +=== List Logstash pipeline API +++++ +List pipeline +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The List Pipelines API enables you to list all centrally-managed Logstash pipelines. +List all centrally-managed Logstash pipelines. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] -[float] +[[logstash-configuration-management-api-list-request]] ==== Request `GET /api/logstash/pipelines` -[float] -==== Examples - -[source,js] --------------------------------------------------- -GET api/logstash/pipelines --------------------------------------------------- -// KIBANA +[[logstash-configuration-management-api-list-example]] +==== Example -A successful call returns a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -43,4 +38,4 @@ A successful call returns a JSON structure similar to the following example: } -------------------------------------------------- -<1> The username property may or may not be present, depending on whether Elastic Security was enabled when the pipeline was created or last updated. \ No newline at end of file +<1> The `username` property may or may not be present, depending on if security was enabled when the pipeline was created or last updated. diff --git a/docs/api/logstash-configuration-management/retrieve.asciidoc b/docs/api/logstash-configuration-management/retrieve.asciidoc index d98ca54a39e83..de7670ff3026a 100644 --- a/docs/api/logstash-configuration-management/retrieve.asciidoc +++ b/docs/api/logstash-configuration-management/retrieve.asciidoc @@ -1,34 +1,29 @@ [role="xpack"] [[logstash-configuration-management-api-retrieve]] -=== Retrieve Pipeline +=== Retrieve pipeline API +++++ +Retrieve pipeline +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The Retrieve Pipeline API enables you to retrieve a centrally-managed Logstash pipeline. +Retrieves a centrally-managed Logstash pipeline. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] -[float] +[[logstash-configuration-management-api-retrieve-request]] ==== Request `GET /api/logstash/pipeline/` -[float] -==== Path Parameters - -`id` (required):: - (string) ID for pipeline. +[[logstash-configuration-management-api-retrieve-path-params]] +==== Path parameters -[float] -==== Examples - -[source,js] --------------------------------------------------- -GET api/logstash/pipeline/hello-world --------------------------------------------------- -// KIBANA +`id`:: + (Required, string) The pipeline ID. + +[[logstash-configuration-management-api-retrieve-example]] +==== Example -A successful call returns a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- diff --git a/docs/api/role-management.asciidoc b/docs/api/role-management.asciidoc index 2f4aa75d46d32..622d26571cd6e 100644 --- a/docs/api/role-management.asciidoc +++ b/docs/api/role-management.asciidoc @@ -1,20 +1,17 @@ [role="xpack"] [[role-management-api]] -== Kibana Role Management API +== Kibana role management APIs -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying mechanism of enforcing role based access control is stable, but the APIs for managing the roles are currently experimental."] +Manage the roles that grant <>. -The role management API allows people to manage roles that grant <>. -It is *not* supported to do so using the -{ref}/security-api.html#security-role-apis[{es} role management APIs], and doing -so will likely cause {kib}'s authorization to behave unexpectedly. +WARNING: Do not use the {ref}/security-api.html#security-role-apis[{es} role management APIs] to manage {kib} roles. -NOTE: You cannot access these endpoints via the Console in Kibana. - -* <> -* <> -* <> +* <> +* <> +* <> +* <> include::role-management/put.asciidoc[] include::role-management/get.asciidoc[] +include::role-management/get-all.asciidoc[] include::role-management/delete.asciidoc[] diff --git a/docs/api/role-management/delete.asciidoc b/docs/api/role-management/delete.asciidoc index 3a2eb6cfb731f..41cd1151ab6eb 100644 --- a/docs/api/role-management/delete.asciidoc +++ b/docs/api/role-management/delete.asciidoc @@ -1,26 +1,29 @@ [[role-management-api-delete]] -=== Delete role +=== Delete role API +++++ +Delete role +++++ -experimental["This API is experimental and may be changed or removed completely in a future release. Although the underlying mechanism of enforcing role-based access control is stable, the APIs for managing the roles are currently experimental."] +Deletes a {kib} role. -NOTE: You cannot access this endpoint via the Console in Kibana. +experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying mechanism of enforcing role based access control is stable, but the APIs for managing the roles are currently experimental."] -==== Authorization +[[role-management-api-delete-prereqs]] +==== Prerequisite -To use this API, you must have at least the `manage_security` cluster privilege. +To use the delete role API, you must have the `manage_security` cluster privilege. +[[role-management-api-delete-request-body]] ==== Request -To delete a role, submit a DELETE request to the `/api/security/role/` -endpoint: +`DELETE /api/security/role/my_admin_role` -[source,js] --------------------------------------------------- -DELETE /api/security/role/my_admin_role --------------------------------------------------- -// KIBANA +[[role-management-api-delete-response-codes]] +==== Response codes -==== Response - -If the role is successfully deleted, the response code is `204`; otherwise, the response -code is 404. +`204`:: + Indicates a successful call. + +`404`:: + Indicates an unsuccessful call. + \ No newline at end of file diff --git a/docs/api/role-management/get-all.asciidoc b/docs/api/role-management/get-all.asciidoc new file mode 100644 index 0000000000000..da728697b0b56 --- /dev/null +++ b/docs/api/role-management/get-all.asciidoc @@ -0,0 +1,80 @@ +[[role-management-api-get]] +=== Get all {kib} roles API +++++ +Get all roles +++++ + +Retrieves all {kib} roles. + +experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying mechanism of enforcing role based access control is stable, but the APIs for managing the roles are currently experimental."] + +[[role-management-api-get-prereqs]] +==== Prerequisite + +To use the get role API, you must have the `manage_security` cluster privilege. + +[[role-management-api-retrieve-all-request-body]] +==== Request + +`GET /api/security/role` + +[[role-management-api-retrieve-all-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[role-management-api-retrieve-all-example]] +==== Example + +The API returns the following: + +[source,js] +-------------------------------------------------- +[ + { + "name": "my_kibana_role", + "metadata" : { + "version" : 1 + }, + "transient_metadata": { + "enabled": true + }, + "elasticsearch": { + "indices": [ ], + "cluster": [ ], + "run_as": [ ] + }, + "kibana": [{ + "base": [ + "all" + ], + "feature": {}, + "spaces": [ + "*" + ] + }] + }, + { + "name": "my_admin_role", + "metadata" : { + "version" : 1 + }, + "transient_metadata": { + "enabled": true + }, + "elasticsearch": { + "cluster" : [ "all" ], + "indices" : [ { + "names" : [ "index1", "index2" ], + "privileges" : [ "all" ], + "field_security" : { + "grant" : [ "title", "body" ] + }, + "query" : "{\"match\": {\"title\": \"foo\"}}" + } ], + }, + "kibana": [ ] + } +] +-------------------------------------------------- \ No newline at end of file diff --git a/docs/api/role-management/get.asciidoc b/docs/api/role-management/get.asciidoc index ce878588abcd4..c6292bd3654ff 100644 --- a/docs/api/role-management/get.asciidoc +++ b/docs/api/role-management/get.asciidoc @@ -1,101 +1,33 @@ -[[role-management-api-get]] -=== Get Role +[[role-management-specific-api-get]] +=== Get specific role API +++++ +Get specific role +++++ -experimental["This API is experimental and may be changed or removed completely in a future release. Although the underlying mechanism of enforcing role-based access control is stable, the APIs for managing the roles are currently experimental."] +Retrieves a specific role. -Retrieves all {kib} roles, or a specific role. +experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying mechanism of enforcing role based access control is stable, but the APIs for managing the roles are currently experimental."] -NOTE: You cannot access this endpoint via the Console in Kibana. +[[role-management-specific-api-get-prereqs]] +==== Prerequisite -==== Authorization - -To use this API, you must have at least the `manage_security` cluster privilege. - -==== Get all {kib} roles +To use the get specific role API, you must have the `manage_security` cluster privilege. +[[role-management-specific-api-retrieve-all-request-body]] ===== Request -To retrieve all roles, issue a GET request to the -/api/security/role endpoint. - -[source,js] --------------------------------------------------- -GET /api/security/role --------------------------------------------------- -// KIBANA - -===== Response - -A successful call returns a response code of `200` and a response body containing a JSON -representation of the roles. +`GET /api/security/role/my_restricted_kibana_role` -[source,js] --------------------------------------------------- -[ - { - "name": "my_kibana_role", - "metadata" : { - "version" : 1 - }, - "transient_metadata": { - "enabled": true - }, - "elasticsearch": { - "indices": [ ], - "cluster": [ ], - "run_as": [ ] - }, - "kibana": [{ - "base": [ - "all" - ], - "feature": {}, - "spaces": [ - "*" - ] - }] - }, - { - "name": "my_admin_role", - "metadata" : { - "version" : 1 - }, - "transient_metadata": { - "enabled": true - }, - "elasticsearch": { - "cluster" : [ "all" ], - "indices" : [ { - "names" : [ "index1", "index2" ], - "privileges" : [ "all" ], - "field_security" : { - "grant" : [ "title", "body" ] - }, - "query" : "{\"match\": {\"title\": \"foo\"}}" - } ], - }, - "kibana": [ ] - } -] --------------------------------------------------- - -==== Get a specific role - -===== Request - -To retrieve a specific role, issue a GET request to -the `/api/security/role/` endpoint: - -[source,js] --------------------------------------------------- -GET /api/security/role/my_restricted_kibana_role --------------------------------------------------- -// KIBANA +[[role-management-specific-api-retrieve-all-response-codes]] +==== Response code -===== Response +`200`:: + Indicates a successful call. + +[[role-management-specific-api-retrieve-all-example]] +===== Example -A successful call returns a response code of `200` and a response body containing a JSON -representation of the role. +The API returns the following: [source,js] -------------------------------------------------- diff --git a/docs/api/role-management/put.asciidoc b/docs/api/role-management/put.asciidoc index e02445adfb19c..9a636da2f7ff7 100644 --- a/docs/api/role-management/put.asciidoc +++ b/docs/api/role-management/put.asciidoc @@ -1,52 +1,60 @@ [[role-management-api-put]] -=== Create or Update Role +=== Create or update role API +++++ +Create or update role +++++ -experimental["This API is experimental and may be changed or removed completely in a future release. Although the underlying mechanism of enforcing role-based access control is stable, the APIs for managing the roles are currently experimental."] - -Creates a new {kib} role or updates the attributes of an existing role. {kib} roles are stored in the +Creates a new {kib} role, or updates the attributes of an existing role. {kib} roles are stored in the {es} native realm. -NOTE: You cannot access this endpoint via the Console in Kibana. +experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying mechanism of enforcing role based access control is stable, but the APIs for managing the roles are currently experimental."] -==== Authorization +[[role-management-api-put-request]] +==== Request -To use this API, you must have at least the `manage_security` cluster privilege. +`PUT /api/security/role/my_kibana_role` -==== Request +[[role-management-api-put-prereqs]] +==== Prerequisite -To create or update a role, issue a PUT request to the -`/api/security/role/` endpoint. +To use the create or update role API, you must have the `manage_security` cluster privilege. -[source,js] --------------------------------------------------- -PUT /api/security/role/my_kibana_role --------------------------------------------------- +[[role-management-api-response-body]] +==== Request body + +`metadata`:: + (Optional, object) In the `metadata` object, keys that begin with `_` are reserved for system usage. -==== Request Body +`elasticsearch`:: + (Optional, object) {es} cluster and index privileges. Valid keys include `cluster`, `indices`, and `run_as`. For more information, see {xpack-ref}/defining-roles.html[Defining Roles]. -The following parameters can be specified in the body of a PUT request to add or update a role: +`kibana`:: + (list) Objects that specify the <> for the role: -`metadata`:: (object) Optional meta-data. Within the `metadata` object, keys -that begin with `_` are reserved for system usage. +`base` ::: + (Optional, list) A base privilege. When specified, the base must be `["all"]` or `["read"]`. + When the `base` privilege is specified, you are unable to use the `feature` section. + "all" grants read/write access to all {kib} features for the specified spaces. + "read" grants read-only access to all {kib} features for the specified spaces. -`elasticsearch`:: (object) Optional {es} cluster and index privileges, valid keys are -`cluster`, `indices` and `run_as`. For more information, see {xpack-ref}/defining-roles.html[Defining Roles]. +`feature` ::: + (object) Contains privileges for specific features. + When the `feature` privileges are specified, you are unable to use the `base` section. + To retrieve a list of available features, use the <>. -`kibana`:: (list) A list of objects that specifies the <> for this role: -`base` ::: (list) An optional base privilege. If specified, must either be `["all"]` or `["read"]`. -The `feature` section cannot be used if a base privilege is specified here. You must use one or the other. -"all" grants read/write access to all Kibana features for the specified spaces. -"read" grants read-only access to all Kibana features for the specified spaces. +`spaces` ::: + (list) The spaces to apply the privileges to. + To grant access to all spaces, set to `["*"]`, or omit the value. -`feature` ::: (object) Object containing privileges for specific features. -The `base` section cannot be used if feature privileges are specified here. You must use one or the other. -Use the <> to retrieve a list of available features. +[[role-management-api-put-response-codes]] +==== Response code -`spaces` ::: (list) The spaces these privileges should be applied to. -To grant access to all spaces, set this to `["*"]`, or omit the value. +`204`:: + Indicates a successful call. -===== Example 1 -Granting access to various features in all spaces. +===== Examples + +Grant access to various features in all spaces: [source,js] -------------------------------------------------- @@ -115,8 +123,7 @@ PUT /api/security/role/my_kibana_role -------------------------------------------------- // KIBANA -===== Example 2 -Granting "dashboard only" access to only the Marketing space. +Grant dashboard-only access to only the Marketing space: [source,js] -------------------------------------------------- @@ -142,9 +149,9 @@ PUT /api/security/role/my_kibana_role ] } -------------------------------------------------- +// KIBANA -===== Example 3 -Granting full access to all features in the Default space. +Grant full access to all features in the Default space: [source,js] -------------------------------------------------- @@ -169,9 +176,9 @@ PUT /api/security/role/my_kibana_role ] } -------------------------------------------------- +// KIBANA -===== Example 4 -Granting different access to different spaces. +Grant different access to different spaces: [source,js] -------------------------------------------------- @@ -205,10 +212,9 @@ PUT /api/security/role/my_kibana_role ] } -------------------------------------------------- +// KIBANA - -===== Example 5 -Granting access to both Kibana and Elasticsearch. +Grant access to {kib} and Elasticsearch: [source,js] -------------------------------------------------- @@ -240,7 +246,4 @@ PUT /api/security/role/my_kibana_role ] } -------------------------------------------------- - -==== Response - -A successful call returns a response code of `204` and no response body. +// KIBANA diff --git a/docs/api/saved-objects.asciidoc b/docs/api/saved-objects.asciidoc index 78aba32428294..6c7e015f9f81c 100644 --- a/docs/api/saved-objects.asciidoc +++ b/docs/api/saved-objects.asciidoc @@ -1,26 +1,21 @@ [[saved-objects-api]] -== Saved Objects API +== Saved objects APIs -The saved objects API allows people to manage Kibana saved objects, including -but not limited to dashboards, visualizations, and index patterns. +Manage {kib} saved objects, including dashboards, visualizations, index patterns, and more. -Traditionally, developers would perform this level of integration by writing -documents directly to the `.kibana` index. *Do not do this!* Writing directly -to the `.kibana` index is not safe and it _will_ result in corrupted data that -permanently breaks Kibana in a future version. +WARNING: Do not write documents directly to the `.kibana` index. When you write directly +to the `.kibana` index, the data becomes corrupted and permanently breaks future {kib} versions. -NOTE: You cannot access these endpoints via the Console in Kibana. - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> include::saved-objects/get.asciidoc[] include::saved-objects/bulk_get.asciidoc[] diff --git a/docs/api/saved-objects/bulk_create.asciidoc b/docs/api/saved-objects/bulk_create.asciidoc index 1e749cb67c472..a1b017de6e760 100644 --- a/docs/api/saved-objects/bulk_create.asciidoc +++ b/docs/api/saved-objects/bulk_create.asciidoc @@ -1,61 +1,60 @@ [[saved-objects-api-bulk-create]] -=== Bulk Create Objects +=== Bulk create saved objects API +++++ +Bulk create objects +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The bulk-create saved object API enables you to persist multiple Kibana saved -objects. +Create multiple {kib} saved objects. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-bulk-create-request]] ==== Request `POST /api/saved_objects/_bulk_create` +[[saved-objects-api-bulk-create-query-params]] +==== Query parameters -==== Query Parameters - -`overwrite` (optional):: - (boolean) If true, will overwrite the document with the same ID. - +`overwrite`:: + (Optional, boolean) When `true`, overwrites the document with the same ID. -==== Request Body +[[saved-objects-api-bulk-create-request-body]] +==== Request body -The request body must be a JSON array containing objects, each of which -contains the following properties: +`type`:: + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet`. -`type` (required):: - (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` +`id`:: + (Optional, string) Specifies an ID instead of using a randomly generated ID. -`id` (optional):: - (string) Enables specifying an ID to use, as opposed to one being randomly generated +`attributes`:: + (Required, object) The data that you want to create. -`attributes` (required):: - (object) The data to persist - -`references` (optional):: - (array) An array of objects with `name`, `id`, and `type` properties that describe the other saved objects this object references. The `name` can be used in the attributes to refer to the other saved object, but never the `id`, which may be updated automatically in the future during migrations or import/export. - -`version` (optional):: - (number) Enables specifying a version +`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. +`version`:: + (Optional, number) Specifies the version. +[[saved-objects-api-bulk-create-response-body]] ==== Response body -The response body will have a top level `saved_objects` property that contains -an array of objects, which represent the response for each of the requested -objects. The order of the objects in the response is identical to the order of -the objects in the request. +`saved_objects`:: + (array) Top-level property the contains objects that represent the response for each of the requested objects. The order of the objects in the response is identical to the order of the objects in the request. -For any saved object that could not be persisted, an error object will exist in its -place. +Saved objects that are unable to persist are replaced with an error object. +[[saved-objects-api-bulk-create-codes]] +==== Response code -==== Examples +`200`:: + Indicates a successful call. -The following example attempts to persist an index pattern with id -`my-pattern` and a dashboard with id `my-dashboard`, but only the index pattern -could be persisted because there was an id collision with `my-dashboard` as a saved object with that id alread exists. +[[saved-objects-api-bulk-create-example]] +==== Example + +Create an index pattern with the `my-pattern` ID, and a dashboard with the `my-dashboard` ID: [source,js] -------------------------------------------------- @@ -79,8 +78,7 @@ POST api/saved_objects/_bulk_create -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -105,3 +103,5 @@ containing a JSON structure similar to the following example: ] } -------------------------------------------------- + +There is already a saved object with the `my-dashboard` ID, so only the index pattern is created. diff --git a/docs/api/saved-objects/bulk_get.asciidoc b/docs/api/saved-objects/bulk_get.asciidoc index 564698c9f00c8..9242b2e7d89d3 100644 --- a/docs/api/saved-objects/bulk_get.asciidoc +++ b/docs/api/saved-objects/bulk_get.asciidoc @@ -1,46 +1,48 @@ [[saved-objects-api-bulk-get]] -=== Bulk Get Objects +=== Bulk get objects API +++++ +Bulk get objects +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The bulk-get saved object API enables you to retrieve multiple Kibana saved -objects by id. +Retrieves multiple {kib} saved objects by ID. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-bulk-get-request]] ==== Request `POST /api/saved_objects/_bulk_get` +[[saved-objects-api-bulk-get-request-body]] ==== Request Body -The request body must be a JSON array containing objects, each of which -contains the following properties: +`type`:: + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet`. -`type` (required):: - (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` +`id`:: + (Required, string) ID of the retrieved object. -`id` (required):: - (string) ID of object to retrieve +`fields`:: + (Optional, array) The fields returned in the object response. + +[[saved-objects-api-bulk-get-response-body]] +==== Response body -`fields` (optional):: - (array) The fields to return in the object's response +`saved_objects`:: + (array) Top-level property the contains objects that represent the response for each of the requested objects. The order of the objects in the response is identical to the order of the objects in the request. -==== Response body +Saved objects that are unable to persist are replaced with an error object. -The response body will have a top level `saved_objects` property that contains -an array of objects, which represent the response for each of the requested -objects. The order of the objects in the response is identical to the order of -the objects in the request. +[[saved-objects-api-bulk-get-body-codes]] +==== Response code -For any saved object that could not be found, an error object will exist in its -place. +`200`:: + Indicates a successfully call. -==== Examples +[[saved-objects-api-bulk-get-body-example]] +==== Example -The following example attempts to retrieve an index pattern with id -`my-pattern` and a dashboard with id `my-dashboard`, but only the index pattern -exists. +Retrieve an index pattern with the `my-pattern` ID, and a dashboard with the `my-dashboard` ID: [source,js] -------------------------------------------------- @@ -58,8 +60,7 @@ POST api/saved_objects/_bulk_get -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -84,3 +85,5 @@ containing a JSON structure similar to the following example: ] } -------------------------------------------------- + +Only the index pattern exists. diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc index c4a2cf260f7d9..2277305156548 100644 --- a/docs/api/saved-objects/create.asciidoc +++ b/docs/api/saved-objects/create.asciidoc @@ -1,45 +1,56 @@ [[saved-objects-api-create]] -=== Create Object +=== Create saved object API +++++ +Create object +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The create saved object API enables you to persist a Kibana saved object. +Create a {kib} saved object. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-create-request]] ==== Request `POST /api/saved_objects/` + `POST /api/saved_objects//` -==== Path Parameters - -`type` (required):: - (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` +[[saved-objects-api-create-path-params]] +==== Path parameters -`id` (optional):: - (string) Enables specifying an ID to use, as opposed to one being randomly generated +``:: + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet`. +``:: + (Optional, string) Specifies an ID instead of using a randomly generated ID. -==== Query Parameters +[[saved-objects-api-create-query-params]] +==== Query parameters -`overwrite` (optional):: - (boolean) If true, will overwrite the document with the same ID. +`overwrite`:: + (Optional, boolean) When true, overwrites the document with the same ID. +[[saved-objects-api-create-request-body]] +==== Request body -==== Request Body +`attributes`:: + (Required, object) The data that you want to create. ++ +WARNING: When you create saved objects, attributes are not validated, which allows you to pass +arbitrary and ill-formed data into the API that can break {kib}. Make sure +any data that you send to the API is properly formed. -`attributes` (required):: - (object) The data to persist +`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. -`references` (optional):: - (array) An array of objects with `name`, `id`, and `type` properties that describe the other saved objects this object references. The `name` can be used in the attributes to refer to the other saved object, but never the `id`, which may be updated automatically in the future during migrations or import/export. +[[saved-objects-api-create-request-codes]] +==== Response code -==== Examples - -The following example creates an index pattern object with a pattern of -`my-pattern-*`. +`200`:: + Indicates a successful call. + +[[saved-objects-api-create-example]] +==== Example [source,js] -------------------------------------------------- @@ -52,8 +63,7 @@ POST api/saved_objects/index-pattern/my-pattern -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -67,11 +77,4 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -<1> If `my-pattern` was not specified in the path, a unique ID would have been -generated. - -==== Known issues - -1. *Attributes are not validated at creation time*. This means you can pass -arbitrary and ill-formed data into this API that can break Kibana. Make sure -any data you send to this API is properly formed. +<1> When `my-pattern` is unspecified in the path, a unique ID is automatically generated. diff --git a/docs/api/saved-objects/delete.asciidoc b/docs/api/saved-objects/delete.asciidoc index c303edf2ed422..cf669494d9160 100644 --- a/docs/api/saved-objects/delete.asciidoc +++ b/docs/api/saved-objects/delete.asciidoc @@ -1,34 +1,41 @@ [[saved-objects-api-delete]] -=== Delete Object +=== Delete object API +++++ +Delete object +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +Remove a {kib} saved object. -The delete saved object API permanently removes a Kibana saved object. Once a -saved object has been deleted, _it cannot be recovered_. +WARNING: Once you delete a saved object, _it cannot be recovered_. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-delete-request]] ==== Request `DELETE /api/saved_objects//` -==== Path Parameters +[[saved-objects-api-delete-path-params]] +==== Path parameters -`type` (required):: - (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` +`type`:: + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet`. -`id` (required):: - (string) Object ID being removed +`id`:: + (Required, string) The object ID that you want to remove. +[[saved-objects-api-delete-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. ==== Examples -The following example deletes an index pattern object with an ID of `my-pattern` +Delete an index pattern object with the `my-pattern` ID: [source,js] -------------------------------------------------- DELETE api/saved_objects/index-pattern/my-pattern -------------------------------------------------- // KIBANA - -A successful call returns a response code of `200`. diff --git a/docs/api/saved-objects/export.asciidoc b/docs/api/saved-objects/export.asciidoc index 4cda4dd6278df..424aae8ace4d7 100644 --- a/docs/api/saved-objects/export.asciidoc +++ b/docs/api/saved-objects/export.asciidoc @@ -1,33 +1,47 @@ [[saved-objects-api-export]] -=== Export Objects +=== Export objects API +++++ +Export objects +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The export saved objects API enables you to retrieve a set of saved objects that can later be imported into Kibana. +Retrieve a set of saved objects that you want to import into {kib}. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-export-request]] ==== Request `POST /api/saved_objects/_export` -==== Request Body -`type` (optional):: - (array|string) The saved object type(s) that the export should be limited to -`objects` (optional):: - (array) A list of objects to export -`includeReferencesDeep` (optional):: - (boolean) This will make the exported objects include all the referenced objects needed +[[saved-objects-api-export-request-request-body]] +==== Request body + +`type`:: + (Optional, array|string) The saved object types to include in the export. + +`objects`:: + (Optional, array) A list of objects to export. + +`includeReferencesDeep`:: + (Optional, boolean) Includes all of the referenced objects in the exported objects. -Note: At least `type` or `objects` must be passed in. +TIP: You must include `type` or `objects` in the request body. +[[saved-objects-api-export-request-response-body]] ==== Response body -The response body will have a format of newline delimited JSON. +The format of the response body includes newline delimited JSON. +[[export-objects-api-create-request-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[ssaved-objects-api-create-example]] ==== Examples -The following example exports all index pattern saved objects. +Export all index pattern saved objects: [source,js] -------------------------------------------------- @@ -38,9 +52,7 @@ POST api/saved_objects/_export -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` along with the exported objects as the response body. - -The following example exports specific saved objects. +Export a specific saved object: [source,js] -------------------------------------------------- @@ -54,4 +66,4 @@ POST api/saved_objects/_export ] } -------------------------------------------------- -// KIBANA \ No newline at end of file +// KIBANA diff --git a/docs/api/saved-objects/find.asciidoc b/docs/api/saved-objects/find.asciidoc index 43fea5b5116c6..ef35a6abb4b99 100644 --- a/docs/api/saved-objects/find.asciidoc +++ b/docs/api/saved-objects/find.asciidoc @@ -1,51 +1,60 @@ [[saved-objects-api-find]] -=== Find Objects +=== Find objects API +++++ +Find objects +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The find saved object API enables you to retrieve a paginated set of Kibana -saved objects by various conditions. +Retrieve a paginated set of {kib} saved objects by various conditions. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-find-request]] ==== Request `GET /api/saved_objects/_find` +[[saved-objects-api-find-query-params]] ==== Query Parameters -`type` (required):: - (array|string) The saved object type(s) that the response should be limited to -`per_page` (optional):: - (number) The number of objects to return per page -`page` (optional):: - (number) The page of objects to return -`search` (optional):: - (string) A {ref}/query-dsl-simple-query-string-query.html[simple_query_string] Elasticsearch query to filter the objects in the response -`default_search_operator` (optional):: - (string) The default operator to use for the `simple_query_string` -`search_fields` (optional):: - (array|string) The fields to perform the `simple_query_string` parsed query against -`fields` (optional):: - (array|string) The fields to return in the response -`sort_field` (optional):: - (string) The field on which the response will be sorted -`has_reference` (optional):: - (object) Filters to objects having a relationship with the type and id combination - -[NOTE] -============================================== - -As objects change in Kibana, the results on each page of this response can -change. This makes the `find` API suitable for traditional paginated results -but not a reliable way to safely export large amounts of data. - -============================================== +`type`:: + (Required, array|string) The saved object types to include in the export. + +`per_page`:: + (Optional, number) The number of objects to return per page. + +`page`:: + (Optional, number) The page of objects to return. + +`search`:: + (Optional, string) An Elasticsearch {ref}/query-dsl-simple-query-string-query.html[simple_query_string] query that filters the objects in the response. + +`default_search_operator`:: + (Optional, string) The default operator to use for the `simple_query_string`. + +`search_fields`:: + (Optional, array|string) The fields to perform the `simple_query_string` parsed query against. + +`fields`:: + (Optional, array|string) The fields to return in the response. + +`sort_field`:: + (Optional, string) The field that sorts the response. + +`has_reference`:: + (Optional, object) Filters to objects that have a relationship with the type and ID combination. + +NOTE: As objects change in {kib}, the results on each page of the response also +change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data. + +[[saved-objects-api-find-request-codes]] +==== Response code + +`200`:: + Indicates a successful call. ==== Examples -The following example attempts to find index patterns with titles that start -with `my`: +Find index patterns with titles that start with `my`: [source,js] -------------------------------------------------- @@ -53,8 +62,7 @@ GET api/saved_objects/_find?type=index-pattern&search_fields=title&search=my* -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -73,11 +81,7 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -[NOTE] -.Multiple values for a parameter -============================================== - -For parameters that can accept multiple values (e.g. `fields`), repeat the +For parameters that accept multiple values (e.g. `fields`), repeat the query parameter for each value: [source,js] @@ -86,4 +90,3 @@ GET api/saved_objects/_find?fields=id&fields=title -------------------------------------------------- // KIBANA -============================================== diff --git a/docs/api/saved-objects/get.asciidoc b/docs/api/saved-objects/get.asciidoc index cb9b577d46e7a..08c15ddaf2eb5 100644 --- a/docs/api/saved-objects/get.asciidoc +++ b/docs/api/saved-objects/get.asciidoc @@ -1,30 +1,37 @@ [[saved-objects-api-get]] -=== Get Object +=== Get object API +++++ +Get object +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The get saved object API enables you to retrieve a single Kibana saved object -by id. +Retrieve a single {kib} saved object by ID. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-get-request]] ==== Request `GET /api/saved_objects//` -==== Path Parameters +[[saved-objects-api-get-params]] +==== Path parameters + +`type`:: + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet`. -`type` (required):: - (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` +`id`:: + (Required, string) The ID of the object to retrieve. -`id` (required):: - (string) ID of object to retrieve +[[saved-objects-api-get-codes]] +==== Response code +`200`:: + Indicates a successful call. -==== Examples +[[saved-objects-api-get-example]] +==== Example -The following example retrieves the index pattern object with an id of -`my-pattern`. +Retrieve the index pattern object with the `my-pattern` ID: [source,js] -------------------------------------------------- @@ -32,8 +39,7 @@ GET api/saved_objects/index-pattern/my-pattern -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- diff --git a/docs/api/saved-objects/import.asciidoc b/docs/api/saved-objects/import.asciidoc index f5bc9d184bea4..ee4517687a448 100644 --- a/docs/api/saved-objects/import.asciidoc +++ b/docs/api/saved-objects/import.asciidoc @@ -1,44 +1,60 @@ [[saved-objects-api-import]] -=== Import Objects +=== Import objects API +++++ +Import objects +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] - -The import saved objects API enables you to create a set of Kibana saved objects from a file created by the export API. +Create a set of {kib} saved objects from a file created by the export API. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[saved-objects-api-import-request]] ==== Request `POST /api/saved_objects/_import` -==== Query Parameters +[[saved-objects-api-import-query-params]] +==== Query parameter -`overwrite` (optional):: - (boolean) Overwrite saved objects if they exist already +`overwrite`:: + (Optional, boolean) Overwrites saved objects. +[[saved-objects-api-import-request-body]] ==== Request body -The request body must be of type multipart/form-data. +The request body must include the multipart/form-data type. `file`:: A file exported using the export API. +[[saved-objects-api-import-response-body]] ==== Response body -The response body will have a top level `success` property that indicates -if the import was successful or not as well as a `successCount` indicating how many records are successfully imported. -In the scenario the import wasn't successful a top level `errors` array will contain the objects that failed to import. +`success`:: + Top-level property that indicates if the import was successful. + +`successCount`:: + Indicates the number of successfully imported records. + +`errors`:: + (array) Indicates the import was unsuccessful and specifies the objects that failed to import. + +[[saved-objects-api-import-codes]] +==== Response code + +`200`:: + Indicates a successful call. ==== Examples -The following example imports an index pattern and dashboard. +Import an index pattern and dashboard: [source,js] -------------------------------------------------- -$ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson +$ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson <1> -------------------------------------------------- -The `file.ndjson` file would contain the following. +The `file.ndjson` file contains the following: [source,js] -------------------------------------------------- @@ -46,8 +62,7 @@ The `file.ndjson` file would contain the following. {"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}} -------------------------------------------------- -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -57,14 +72,14 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -The following example imports an index pattern and dashboard but has a conflict on the index pattern. +Import an index pattern and dashboard that includes a conflict on the index pattern: [source,js] -------------------------------------------------- $ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson -------------------------------------------------- -The `file.ndjson` file would contain the following. +The `file.ndjson` file contains the following: [source,js] -------------------------------------------------- @@ -72,8 +87,7 @@ The `file.ndjson` file would contain the following. {"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}} -------------------------------------------------- -The call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -93,14 +107,14 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -The following example imports a visualization and dashboard but the index pattern for the visualization reference doesn't exist. +Import a visualization and dashboard with an index pattern for the visualization reference that doesn't exist: [source,js] -------------------------------------------------- $ curl -X POST "localhost:5601/api/saved_objects/_import" -H "kbn-xsrf: true" --form file=@file.ndjson -------------------------------------------------- -The `file.ndjson` file would contain the following. +The `file.ndjson` file contains the following: [source,js] -------------------------------------------------- @@ -108,8 +122,7 @@ The `file.ndjson` file would contain the following. {"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"},"references":[{"name":"ref_0","type":"visualization","id":"my-vis"}]} -------------------------------------------------- -The call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- diff --git a/docs/api/saved-objects/resolve_import_errors.asciidoc b/docs/api/saved-objects/resolve_import_errors.asciidoc index ab376e97aa25d..848ae504dbfa5 100644 --- a/docs/api/saved-objects/resolve_import_errors.asciidoc +++ b/docs/api/saved-objects/resolve_import_errors.asciidoc @@ -1,50 +1,73 @@ [[saved-objects-api-resolve-import-errors]] -=== Resolve Import Errors +=== Resolve import errors API +++++ +Resolve import errors +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +Resolve errors from the import API. + +To resolve errors, you can: -The resolve import errors API enables you to resolve errors given by the import API by either retrying certain saved objects, overwriting specific saved objects or changing references to different saved objects. +* Retry certain saved objects -Note: You cannot access this endpoint via the Console in Kibana. +* Overwrite specific saved objects +* Change references to different saved objects + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +[[saved-objects-api-resolve-import-errors-request]] ==== Request `POST /api/saved_objects/_resolve_import_errors` +[[saved-objects-api-resolve-import-errors-request-body]] ==== Request body -The request body must be of type multipart/form-data. +The request body must include the multipart/form-data type. `file`:: The same file given to the import API. `retries`:: - (array) A list of `type`, `id`, `replaceReferences` and `overwrite` objects to retry importing. The property `replaceReferences` is a list of `type`, `from` and `to` used to change the object's references. + (array) A list of `type`, `id`, `replaceReferences`, and `overwrite` objects to retry. The property `replaceReferences` is a list of `type`, `from`, and `to` used to change the object references. +[[saved-objects-api-resolve-import-errors-response-body]] ==== Response body -The response body will have a top level `success` property that indicates -if resolving errors was successful or not as well as a `successCount` indicating how many records are successfully resolved. -In the scenario resolving errors wasn't successful, a top level `errors` array will contain the objects that failed to be resolved. +`success`:: + Top-level property that indicates if the errors successfully resolved. + +`successCount`:: + Indicates the number of successfully resolved records. + +`errors`:: + (array) Specifies the objects that failed to resolve. + +[[saved-objects-api-resolve-import-errors-codes]] +==== Response code + +`200`:: + Indicates a successful call. +[[saved-objects-api-resolve-import-errors-example]] ==== Examples -The following example retries importing a dashboard. +Retry a dashboard import: [source,js] -------------------------------------------------- $ curl -X POST "localhost:5601/api/saved_objects/_resolve_import_errors" -H "kbn-xsrf: true" --form file=@file.ndjson --form retries='[{"type":"dashboard","id":"my-dashboard"}]' -------------------------------------------------- -The `file.ndjson` file would contain the following. +The `file.ndjson` file contains the following: [source,js] -------------------------------------------------- {"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}} -------------------------------------------------- -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -54,14 +77,14 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -The following example resolves errors for a dashboard. This will cause the dashboard to overwrite the existing saved object. +Resolve errors for a dashboard and overwrite the existing saved object: [source,js] -------------------------------------------------- $ curl -X POST "localhost:5601/api/saved_objects/_resolve_import_errors" -H "kbn-xsrf: true" --form file=@file.ndjson --form retries='[{"type":"dashboard","id":"my-dashboard","overwrite":true}]' -------------------------------------------------- -The `file.ndjson` file would contain the following. +The `file.ndjson` file contains the following: [source,js] -------------------------------------------------- @@ -69,8 +92,7 @@ The `file.ndjson` file would contain the following. {"type":"dashboard","id":"my-dashboard","attributes":{"title":"Look at my dashboard"}} -------------------------------------------------- -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -80,22 +102,21 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -The following example resolves errors for a visualization by replacing the index pattern to another. +Resolve errors for a visualization by replacing the index pattern with another: [source,js] -------------------------------------------------- $ curl -X POST "localhost:5601/api/saved_objects/_resolve_import_errors" -H "kbn-xsrf: true" --form file=@file.ndjson --form retries='[{"type":"visualization","id":"my-vis","replaceReferences":[{"type":"index-pattern","from":"missing","to":"existing"}]}]' -------------------------------------------------- -The `file.ndjson` file would contain the following. +The `file.ndjson` file contains the following: [source,js] -------------------------------------------------- {"type":"visualization","id":"my-vis","attributes":{"title":"Look at my visualization"},"references":[{"name":"ref_0","type":"index-pattern","id":"missing"}]} -------------------------------------------------- -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- diff --git a/docs/api/saved-objects/update.asciidoc b/docs/api/saved-objects/update.asciidoc index 092128040d3eb..16b5865f28cd5 100644 --- a/docs/api/saved-objects/update.asciidoc +++ b/docs/api/saved-objects/update.asciidoc @@ -1,38 +1,48 @@ [[saved-objects-api-update]] -=== Update Object +=== Update object API +++++ +Update object +++++ -experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +Update the attributes for an existing {kib} saved object. -The update saved object API enables you to update the attributes for an -existing Kibana saved object. - -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release. +[[saved-objects-api-update-request]] ==== Request `PUT /api/saved_objects//` +[[saved-objects-api-update-path-params]] ==== Path Parameters -`type` (required):: - (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` - -`id` (required):: - (string) ID of object to update +`type`:: + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet`. +`id`:: + (Required, string) The object ID to update. +[[saved-objects-api-update-request-body]] ==== Request Body -`attributes` (required):: - (object) The data to persist +`attributes`:: + (Required, object) The data to persist. ++ +WARNING: When you update, attributes are not validated, which allows you to pass arbitrary and ill-formed data into the API and break {kib}. Make sure 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 this object references. To refer to the other saved object, use `name` in the attributes, but never the `id`, which automatically updates during migrations or import/export. + +[[saved-objects-api-update-errors-codes]] +==== Response code -`references` (optional):: - (array) An array of objects with `name`, `id`, and `type` properties that describe the other saved objects this object references. The `name` can be used in the attributes to refer to the other saved object, but never the `id`, which may be updated automatically in the future during migrations or import/export. +`200`:: + Indicates a successful call. -==== Examples +[[saved-objects-api-update-example]] +==== Example -The following example updates an existing index pattern object identified as -`my-pattern` with a different index pattern title. +Update an existing index pattern object,`my-pattern`, with a different title: [source,js] -------------------------------------------------- @@ -45,8 +55,7 @@ PUT api/saved_objects/index-pattern/my-pattern -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -59,9 +68,3 @@ containing a JSON structure similar to the following example: } } -------------------------------------------------- - -==== Known issues - -1. *Attributes are not validated at update time*. This means you can pass -arbitrary and ill-formed data into this API that can break Kibana. Make sure -any data you send to this API is properly formed. diff --git a/docs/api/spaces-management.asciidoc b/docs/api/spaces-management.asciidoc index 9d34bbd56fe67..fe12ecab12e5c 100644 --- a/docs/api/spaces-management.asciidoc +++ b/docs/api/spaces-management.asciidoc @@ -1,19 +1,21 @@ [role="xpack"] [[spaces-api]] -== Kibana Spaces API +== Kibana Spaces APIs -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Spaces concepts are stable, but the APIs for managing Spaces are currently experimental."] +Manage your {kib} spaces. -The spaces API allows people to manage their spaces within {kib}. - -NOTE: You cannot access these endpoints via the Console in Kibana. - -* <> -* <> -* <> -* <> +* <> +* <> +* <> +* <> +* <> +* <> +*<> include::spaces-management/post.asciidoc[] include::spaces-management/put.asciidoc[] include::spaces-management/get.asciidoc[] +include::spaces-management/get_all.asciidoc[] include::spaces-management/delete.asciidoc[] +include::spaces-management/copy_saved_objects.asciidoc[] +include::spaces-management/resolve_copy_saved_objects_conflicts.asciidoc[] diff --git a/docs/api/spaces-management/copy_saved_objects.asciidoc b/docs/api/spaces-management/copy_saved_objects.asciidoc new file mode 100644 index 0000000000000..34eac49adb398 --- /dev/null +++ b/docs/api/spaces-management/copy_saved_objects.asciidoc @@ -0,0 +1,288 @@ +[role="xpack"] +[[spaces-api-copy-saved-objects]] +=== Copy saved objects to space API +++++ +Copy saved objects to space +++++ + +Copies saved objects from one space to other spaces. + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +//// +Use the appropriate heading levels for your book. +Add anchors for each section. +FYI: The section titles use attributes in case those terms change. +//// + +[[spaces-api-copy-saved-objects-request]] +==== {api-request-title} +//// +This section show the basic endpoint, without the body or optional parameters. +Variables should use <...> syntax. +If an API supports both PUT and POST, include both here. +//// + +`POST /api/spaces/_copy_saved_objects` + +`POST /s//api/spaces/_copy_saved_objects` + + +//// +[[spaces-api-copy-saved-objects-prereqs]] +==== {api-prereq-title} +//// +//// +Optional list of prerequisites. + +For example: + +* A snapshot of an index created in 5.x can be restored to 6.x. You must... +* If the {es} {security-features} are enabled, you must have `write`, `monitor`, +and `manage_follow_index` index privileges... +//// + + +[[spaces-api-copy-saved-objects-desc]] +==== {api-description-title} + +Copy saved objects between spaces. + +It also allows you to automatically copy related objects, so when you copy a `dashboard`, this can automatically copy over the +associated visualizations, index patterns, and saved searches, as required. + +You can request to overwrite any objects that already exist in the target space if they share an ID, or you can use the +<> to do this on a per-object basis. + +//// +Add a more detailed description the context. +Link to related APIs if appropriate. + +Guidelines for parameter documentation +*************************************** +* Use a definition list. +* End each definition with a period. +* Include whether the parameter is Optional or Required and the data type. +* Include default values as the last sentence of the first paragraph. +* Include a range of valid values, if applicable. +* If the parameter requires a specific delimiter for multiple values, say so. +* If the parameter supports wildcards, ditto. +* For large or nested objects, consider linking to a separate definition list. +*************************************** +//// + + +[[spaces-api-copy-saved-objects-path-params]] +==== {api-path-parms-title} +//// +A list of all the parameters within the path of the endpoint (before the query string (?)). + +For example: +``:: +(Required, string) Name of the follower index +//// +`space_id`:: +(Optional, string) Identifies the source space from which saved objects will be copied. If `space_id` is not specified in the URL, the default space is used. + +//// +[[spaces-api-copy-saved-objects-params]] +==== {api-query-parms-title} +//// +//// +A list of the parameters in the query string of the endpoint (after the ?). + +For example: +`wait_for_active_shards`:: +(Optional, integer) Specifies the number of shards to wait on being active before +responding. A shard must be restored from the leader index being active. +Restoring a follower shard requires transferring all the remote Lucene segment +files to the follower index. The default is `0`, which means waiting on none of +the shards to be active. +//// + +[[spaces-api-copy-saved-objects-request-body]] +==== {api-request-body-title} +//// +A list of the properties you can specify in the body of the request. + +For example: +`remote_cluster`:: +(Required, string) The <> that contains +the leader index. + +`leader_index`:: +(Required, string) The name of the index in the leader cluster to follow. +//// +`spaces` :: + (Required, string array) The ids of the spaces the specified object(s) will be copied into. + +`objects` :: + (Required, object array) The saved objects to copy. + `type` ::: + (Required, string) The saved object type. + `id` ::: + (Required, string) The saved object id. + +`includeReferences` :: + (Optional, boolean) When set to `true`, all saved objects related to the specified saved objects will also be copied into the target spaces. The default value is `false`. + +`overwrite` :: + (Optional, boolean) When set to `true`, all conflicts will be automatically overidden. If a saved object with a matching `type` and `id` exists in the target space, then that version will be replaced with the version from the source space. The default value is `false`. + + +[[spaces-api-copy-saved-objects-response-body]] +==== {api-response-body-title} +//// +Response body is only required for detailed responses. + +For example: +`auto_follow_stats`:: + (object) An object representing stats for the auto-follow coordinator. This + object consists of the following fields: + +`auto_follow_stats.number_of_successful_follow_indices`::: + (long) the number of indices that the auto-follow coordinator successfully + followed +... + +//// + +``:: + (object) Specifies the dynamic keys that are included in the response. An object describing the result of the copy operation for this particular space. + `success`::: + (boolean) Indicates if the copy operation was successful. Note that some objects may have been copied even if this is set to `false`. Consult the `successCount` and `errors` properties of the response for additional information. + `successCount`::: + (number) The number of objects that were successfully copied. + `errors`::: + (Optional, array) Collection of any errors that were encountered during the copy operation. If any errors are reported, then the `success` flag will be set to `false`. + `id`:::: + (string) The saved object id which failed to copy. + `type`:::: + (string) The type of saved object which failed to copy. + `error`:::: + (object) The error which caused the copy operation to fail. + `type`::::: + (string) Indicates the type of error. May be one of: `conflict`, `unsupported_type`, `missing_references`, `unknown`. Errors marked as `conflict` may be resolved by using the <>. + +//// +[[spaces-api-copy-saved-objects-response-codes]] +==== {api-response-codes-title} +//// +//// +Response codes are only required when needed to understand the response body. + +For example: +`200`:: +Indicates all listed indices or index aliases exist. + + `404`:: +Indicates one or more listed indices or index aliases **do not** exist. +//// + + +[[spaces-api-copy-saved-objects-example]] +==== {api-examples-title} +//// +Optional brief example. +Use an 'Examples' heading if you include multiple examples. + + +[source,js] +---- +PUT /follower_index/_ccr/follow?wait_for_active_shards=1 +{ + "remote_cluster" : "remote_cluster", + "leader_index" : "leader_index", + "max_read_request_operation_count" : 1024, + "max_outstanding_read_requests" : 16, + "max_read_request_size" : "1024k", + "max_write_request_operation_count" : 32768, + "max_write_request_size" : "16k", + "max_outstanding_write_requests" : 8, + "max_write_buffer_count" : 512, + "max_write_buffer_size" : "512k", + "max_retry_delay" : "10s", + "read_poll_timeout" : "30s" +} +---- +// CONSOLE +// TEST[setup:remote_cluster_and_leader_index] + +The API returns the following result: + +[source,js] +---- +{ + "follow_index_created" : true, + "follow_index_shards_acked" : true, + "index_following_started" : true +} +---- +// TESTRESPONSE +//// + +The following example attempts to copy a dashboard with id `my-dashboard`, including all references from the `default` space to the `marketing` and `sales` spaces. The `marketing` space succeeds, while the `sales` space fails due to a conflict on the underlying index pattern: + +[source,js] +---- +POST /api/spaces/_copy_saved_objects +{ + "objects": [{ + "type": "dashboard", + "id": "my-dashboard" + }], + "spaces": ["marketing", "sales"], + "includeReferences": true +} +---- +// KIBANA + +The API returns the following result: + +[source,js] +---- +{ + "marketing": { + "success": true, + "successCount": 5 + }, + "sales": { + "success": false, + "successCount": 4, + "errors": [{ + "id": "my-index-pattern", + "type": "index-pattern", + "error": { + "type": "conflict" + } + }] + } +} +---- + +The following example successfully copies a visualization with id `my-viz` from the `marketing` space to the `default` space: + +[source,js] +---- +POST /s/marketing/api/spaces/_copy_saved_objects +{ + "objects": [{ + "type": "visualization", + "id": "my-viz" + }], + "spaces": ["default"] +} +---- +// KIBANA + +The API returns the following result: + +[source,js] +---- +{ + "default": { + "success": true, + "successCount": 1 + } +} +---- diff --git a/docs/api/spaces-management/delete.asciidoc b/docs/api/spaces-management/delete.asciidoc index c5cb284f66895..4656e04cd0335 100644 --- a/docs/api/spaces-management/delete.asciidoc +++ b/docs/api/spaces-management/delete.asciidoc @@ -1,27 +1,25 @@ [[spaces-api-delete]] -=== Delete space +=== Delete space API +++++ +Delete space +++++ -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Spaces concepts are stable, but the APIs for managing Spaces are currently experimental."] +Deletes a {kib} space. -[WARNING] -================================================== -Deleting a space will automatically delete all saved objects that belong to that space. This operation cannot be undone! -================================================== +WARNING: When you delete a space, all saved objects that belong to the space are automatically deleted, which is permanent and cannot be undone. -Note: You cannot access this endpoint via the Console in Kibana. +experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Spaces concepts are stable, but the APIs for managing Spaces are currently experimental."] +[[spaces-api-delete-request]] ==== Request -To delete a space, submit a DELETE request to the `/api/spaces/space/` -endpoint: - -[source,js] --------------------------------------------------- -DELETE /api/spaces/space/marketing --------------------------------------------------- -// KIBANA +`DELETE /api/spaces/space/marketing` -==== Response +[[spaces-api-delete-errors-codes]] +==== Response codes -If the space is successfully deleted, the response code is `204`; otherwise, the response -code is 404. +`204`:: + Indicates a successful call. + +`404`:: + Indicates that the request failed. diff --git a/docs/api/spaces-management/get.asciidoc b/docs/api/spaces-management/get.asciidoc index a31aad4c1d6f9..7054aced8c51c 100644 --- a/docs/api/spaces-management/get.asciidoc +++ b/docs/api/spaces-management/get.asciidoc @@ -1,74 +1,28 @@ [[spaces-api-get]] -=== Get Space +=== Get a space API +++++ +Get space +++++ -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Spaces concepts are stable, but the APIs for managing Spaces are currently experimental."] +Retrieves a specified {kib} space. -Retrieves all {kib} spaces, or a specific space. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] -Note: You cannot access this endpoint via the Console in Kibana. +[[spaces-api-get-request]] +==== Request -==== Get all {kib} spaces +`GET /api/spaces/space/marketing` -===== Request +[[spaces-api-get-response-codes]] +==== Response code -To retrieve all spaces, issue a GET request to the -/api/spaces/space endpoint. +`200`:: + Indicates a successful call. -[source,js] --------------------------------------------------- -GET /api/spaces/space --------------------------------------------------- -// KIBANA - -===== Response - -A successful call returns a response code of `200` and a response body containing a JSON -representation of the spaces. - -[source,js] --------------------------------------------------- -[ - { - "id": "default", - "name": "Default", - "description" : "This is the Default Space", - "disabledFeatures": [], - "_reserved": true - }, - { - "id": "marketing", - "name": "Marketing", - "description" : "This is the Marketing Space", - "color": "#aabbcc", - "disabledFeatures": ["apm"], - "initials": "MK" - }, - { - "id": "sales", - "name": "Sales", - "initials": "MK", - "disabledFeatures": ["discover", "timelion"], - }, -] --------------------------------------------------- +[[spaces-api-get-example]] +==== Example -==== Get a specific space - -===== Request - -To retrieve a specific space, issue a GET request to -the `/api/spaces/space/` endpoint: - -[source,js] --------------------------------------------------- -GET /api/spaces/space/marketing --------------------------------------------------- -// KIBANA - -===== Response - -A successful call returns a response code of `200` and a response body containing a JSON -representation of the space. +The API returns the following: [source,js] -------------------------------------------------- @@ -80,4 +34,4 @@ representation of the space. "initials": "MK", "disabledFeatures": [] } --------------------------------------------------- +-------------------------------------------------- \ No newline at end of file diff --git a/docs/api/spaces-management/get_all.asciidoc b/docs/api/spaces-management/get_all.asciidoc new file mode 100644 index 0000000000000..8bed2db31e846 --- /dev/null +++ b/docs/api/spaces-management/get_all.asciidoc @@ -0,0 +1,52 @@ +[[spaces-api-get-all]] +=== Get all {kib} spaces API +++++ +Get all spaces +++++ + +Retrieves all {kib} spaces. + +experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Spaces concepts are stable, but the APIs for managing Spaces are currently experimental."] + +[[spaces-api-get-all-request]] +==== Request + +`GET /api/spaces/space` + +[[spaces-api-get-all-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[spaces-api-get-all-example]] +==== Example + +The API returns the following: + +[source,js] +-------------------------------------------------- +[ + { + "id": "default", + "name": "Default", + "description" : "This is the Default Space", + "disabledFeatures": [], + "_reserved": true + }, + { + "id": "marketing", + "name": "Marketing", + "description" : "This is the Marketing Space", + "color": "#aabbcc", + "disabledFeatures": ["apm"], + "initials": "MK" + }, + { + "id": "sales", + "name": "Sales", + "initials": "MK", + "disabledFeatures": ["discover", "timelion"], + }, +] +-------------------------------------------------- diff --git a/docs/api/spaces-management/post.asciidoc b/docs/api/spaces-management/post.asciidoc index c49ecaf0ffc96..2452fcd73e7fa 100644 --- a/docs/api/spaces-management/post.asciidoc +++ b/docs/api/spaces-management/post.asciidoc @@ -1,40 +1,47 @@ [[spaces-api-post]] -=== Create Space +=== Create space API +++++ +Create space +++++ -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Spaces concepts are stable, but the APIs for managing Spaces are currently experimental."] +Creates a {kib} space. -Creates a new {kib} space. To update an existing space, use the PUT command. - -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[spaces-api-post-request]] ==== Request -To create a space, issue a POST request to the -`/api/spaces/space` endpoint. - -[source,js] --------------------------------------------------- -POST /api/spaces/space --------------------------------------------------- +`POST /api/spaces/space` -==== Request Body +[[spaces-api-post-request-body]] +==== Request body -The following parameters can be specified in the body of a POST request to create a space: +`id`:: + (Required, string) The space ID that is part of the Kibana URL when inside the space. You are unable to change the ID with the update operation. -`id`:: (string) Required identifier for the space. This identifier becomes part of Kibana's URL when inside the space. This cannot be changed by the update operation. +`name`:: + (Required, string) The display name for the space. -`name`:: (string) Required display name for the space. +`description`:: + (Optional, string) The description for the space. -`description`:: (string) Optional description for the space. +`disabledFeatures`:: + (Optional, string array) The list of disabled features for the space. To get a list of available feature IDs, use the <>. -`disabledFeatures`:: (string array) Optional list of features that are disabled for the space. Use the <> to get a list of available features IDs. +`initials`:: + (Optional, string) Specifies the initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters. -`initials`:: (string) Optionally specify the initials shown in the Space Avatar for this space. By default, the initials will be automatically generated from the space name. -If specified, initials should be either 1 or 2 characters. +`color`:: + (Optional, string) Specifies the hexadecimal color code used in the space avatar. By default, the color is automatically generated from the space name. + +[[spaces-api-post-response-codes]] +==== Response codes -`color`:: (string) Optionally specify the hex color code used in the Space Avatar for this space. By default, the color will be automatically generated from the space name. +`200`:: + Indicates a successful call. -===== Example +[[spaces-api-post-example]] +==== Example [source,js] -------------------------------------------------- @@ -49,7 +56,3 @@ POST /api/spaces/space } -------------------------------------------------- // KIBANA - -==== Response - -A successful call returns a response code of `200` with the created Space. diff --git a/docs/api/spaces-management/put.asciidoc b/docs/api/spaces-management/put.asciidoc index 55a6022e729c0..4270d1e9e5496 100644 --- a/docs/api/spaces-management/put.asciidoc +++ b/docs/api/spaces-management/put.asciidoc @@ -1,40 +1,47 @@ [[spaces-api-put]] -=== Update Space +=== Update space API +++++ +Update space +++++ -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Spaces concepts are stable, but the APIs for managing Spaces are currently experimental."] +Updates an existing {kib} space. -Updates an existing {kib} space. To create a new space, use the POST command. - -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[spaces-api-put-api-request]] ==== Request -To update a space, issue a PUT request to the -`/api/spaces/space/` endpoint. +`PUT /api/spaces/space/` -[source,js] --------------------------------------------------- -PUT /api/spaces/space/ --------------------------------------------------- +[[spaces-api-put-request-body]] +==== Request body -==== Request Body +`id`:: + (Required, string) The space ID that is part of the {kib} URL when inside the space. You are unable to change the ID with the update operation. -The following parameters can be specified in the body of a PUT request to update a space: +`name`:: + (Required, string) The display name for the space. -`id`:: (string) Required identifier for the space. This identifier becomes part of Kibana's URL when inside the space. This cannot be changed by the update operation. +`description`:: + (Optional, string) The description for the space. -`name`:: (string) Required display name for the space. +`disabledFeatures`:: + (Optional, string array) The list of disabled features for the space. To get a list of available feature IDs, use the <>. -`description`:: (string) Optional description for the space. +`initials`:: + (Optional, string) Specifies the initials shown in the space avatar. By default, the initials are automatically generated from the space name. Initials must be 1 or 2 characters. -`disabledFeatures`:: (string array) Optional list of features that are disabled for the space. Use the <> to get a list of available features IDs. +`color`:: + (Optional, string) Specifies the hexadecimal color code used in the space avatar. By default, the color is automatically generated from the space name. -`initials`:: (string) Optionally specify the initials shown in the Space Avatar for this space. By default, the initials will be automatically generated from the space name. -If specified, initials should be either 1 or 2 characters. +[[spaces-api-put-response-codes]] +==== Response codes -`color`:: (string) Optioanlly specify the hex color code used in the Space Avatar for this space. By default, the color will be automatically generated from the space name. - -===== Example +`200`:: + Indicates a successful call. + +[[sample-api-example]] +==== Example [source,js] -------------------------------------------------- @@ -49,7 +56,3 @@ PUT /api/spaces/space/marketing } -------------------------------------------------- // KIBANA - -==== Response - -A successful call returns a response code of `200` with the updated Space. diff --git a/docs/api/spaces-management/resolve_copy_saved_objects_conflicts.asciidoc b/docs/api/spaces-management/resolve_copy_saved_objects_conflicts.asciidoc new file mode 100644 index 0000000000000..2f83508632323 --- /dev/null +++ b/docs/api/spaces-management/resolve_copy_saved_objects_conflicts.asciidoc @@ -0,0 +1,265 @@ +[role="xpack"] +[[spaces-api-resolve-copy-saved-objects-conflicts]] +=== Resolve copy saved objects to space conflicts API +++++ +Resolve copy to space conflicts +++++ + +Overwrites specific saved objects that were returned as errors from the <>. + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +//// +Use the appropriate heading levels for your book. +Add anchors for each section. +FYI: The section titles use attributes in case those terms change. +//// + +[[spaces-api-resolve-copy-saved-objects-conflicts-request]] +==== {api-request-title} +//// +This section show the basic endpoint, without the body or optional parameters. +Variables should use <...> syntax. +If an API supports both PUT and POST, include both here. +//// + +`POST /api/spaces/_resolve_copy_saved_objects_errors` + +`POST /s//api/spaces/_resolve_copy_saved_objects_errors` + + + +[[spaces-api-resolve-copy-saved-objects-conflicts-prereqs]] +==== {api-prereq-title} +//// +Optional list of prerequisites. + +For example: + +* A snapshot of an index created in 5.x can be restored to 6.x. You must... +* If the {es} {security-features} are enabled, you must have `write`, `monitor`, +and `manage_follow_index` index privileges... +//// +* Executed the <>, which returned one or more `conflict` errors that you wish to resolve. + +//// +[[spaces-api-resolve-copy-saved-objects-conflicts-desc]] +==== {api-description-title} + +Allows saved objects to be selectively overridden in the target spaces. +//// + +//// +Add a more detailed description the context. +Link to related APIs if appropriate. + +Guidelines for parameter documentation +*************************************** +* Use a definition list. +* End each definition with a period. +* Include whether the parameter is Optional or Required and the data type. +* Include default values as the last sentence of the first paragraph. +* Include a range of valid values, if applicable. +* If the parameter requires a specific delimiter for multiple values, say so. +* If the parameter supports wildcards, ditto. +* For large or nested objects, consider linking to a separate definition list. +*************************************** +//// + + +[[spaces-api-resolve-copy-saved-objects-conflicts-path-params]] +==== {api-path-parms-title} +//// +A list of all the parameters within the path of the endpoint (before the query string (?)). + +For example: +``:: +(Required, string) Name of the follower index +//// +`space_id`:: +(Optional, string) Identifies the source space from which saved objects will be copied. If `space_id` is not specified in the URL, the default space is used. Must be the same value that was used during the failed <> operation. + +//// +[[spaces-api-resolve-copy-saved-objects-conflicts-request-params]] +==== {api-query-parms-title} +//// +//// +A list of the parameters in the query string of the endpoint (after the ?). + +For example: +`wait_for_active_shards`:: +(Optional, integer) Specifies the number of shards to wait on being active before +responding. A shard must be restored from the leader index being active. +Restoring a follower shard requires transferring all the remote Lucene segment +files to the follower index. The default is `0`, which means waiting on none of +the shards to be active. +//// + +[[spaces-api-resolve-copy-saved-objects-conflicts-request-body]] +==== {api-request-body-title} +//// +A list of the properties you can specify in the body of the request. + +For example: +`remote_cluster`:: +(Required, string) The <> that contains +the leader index. + +`leader_index`:: +(Required, string) The name of the index in the leader cluster to follow. +//// +`objects` :: + (Required, object array) The saved objects to copy. Must be the same value that was used during the failed <> operation. + `type` ::: + (Required, string) The saved object type. + `id` ::: + (Required, string) The saved object id. + +`includeReferences` :: + (Optional, boolean) When set to `true`, all saved objects related to the specified saved objects will also be copied into the target spaces. You must set this to the same value that you used when executing the <>. The default value is `false`. + +`retries`:: + (Required, object) The retry operations to attempt. Object keys represent the target space ids. + `` ::: + (Required, array) The the conflicts to resolve for the indicated ``. + `type` :::: + (Required, string) The saved object type. + `id` :::: + (Required, string) The saved object id. + `overwrite` :::: + (Required, boolean) when set to `true`, the saved object from the source space (desigated by the <>) will overwrite the the conflicting object in the destination space. When `false`, this does nothing. + + +[[spaces-api-resolve-copy-saved-objects-conflicts-response-body]] +==== {api-response-body-title} +//// +Response body is only required for detailed responses. + +For example: +`auto_follow_stats`:: + (object) An object representing stats for the auto-follow coordinator. This + object consists of the following fields: + +`auto_follow_stats.number_of_successful_follow_indices`::: + (long) the number of indices that the auto-follow coordinator successfully + followed +... + +//// + +``:: + (object) Specifies the dynamic keys that are included in the response. An object describing the result of the copy operation for this particular space. + `success`::: + (boolean) Indicates if the copy operation was successful. Note that some objects may have been copied even if this is set to `false`. Consult the `successCount` and `errors` properties of the response for additional information. + `successCount`::: + (number) The number of objects that were successfully copied. + `errors`::: + (Optional, array) Collection of any errors that were encountered during the copy operation. If any errors are reported, then the `success` flag will be set to `false`. + `id`:::: + (string) The saved object id which failed to copy. + `type`:::: + (string) The type of saved object which failed to copy. + `error`:::: + (object) The error which caused the copy operation to fail. + `type`::::: + (string) Indicates the type of error. May be one of: `unsupported_type`, `missing_references`, `unknown`. + +//// +[[spaces-api-resolve-copy-saved-objects-conflicts-response-codes]] +==== {api-response-codes-title} +//// +//// +Response codes are only required when needed to understand the response body. + +For example: +`200`:: +Indicates all listed indices or index aliases exist. + + `404`:: +Indicates one or more listed indices or index aliases **do not** exist. +//// + + +[[spaces-api-resolve-copy-saved-objects-conflicts-example]] +==== {api-examples-title} +//// +Optional brief example. +Use an 'Examples' heading if you include multiple examples. + + +[source,js] +---- +PUT /follower_index/_ccr/follow?wait_for_active_shards=1 +{ + "remote_cluster" : "remote_cluster", + "leader_index" : "leader_index", + "max_read_request_operation_count" : 1024, + "max_outstanding_read_requests" : 16, + "max_read_request_size" : "1024k", + "max_write_request_operation_count" : 32768, + "max_write_request_size" : "16k", + "max_outstanding_write_requests" : 8, + "max_write_buffer_count" : 512, + "max_write_buffer_size" : "512k", + "max_retry_delay" : "10s", + "read_poll_timeout" : "30s" +} +---- +// CONSOLE +// TEST[setup:remote_cluster_and_leader_index] + +The API returns the following result: + +[source,js] +---- +{ + "follow_index_created" : true, + "follow_index_shards_acked" : true, + "index_following_started" : true +} +---- +// TESTRESPONSE +//// + +The following example overwrites an index pattern in the marketing space, and a visualization in the sales space. + +[source,js] +---- +POST api/spaces/_resolve_copy_saved_objects_errors +{ + "objects": [{ + "type": "dashboard", + "id": "my-dashboard" + }], + "includeReferences": true, + "retries": { + "marketing": [{ + "type": "index-pattern", + "id": "my-pattern", + "overwrite": true + }], + "sales": [{ + "type": "visualization", + "id": "my-viz", + "overwrite": true + }] + } +} +---- +// KIBANA + +The API returns the following result: + +[source,js] +---- +{ + "marketing": { + "success": true, + "successCount": 1 + }, + "sales": { + "success": true, + "successCount": 1 + } +} +---- diff --git a/docs/api/upgrade-assistant.asciidoc b/docs/api/upgrade-assistant.asciidoc index e53c593138e6c..3cb256c337175 100644 --- a/docs/api/upgrade-assistant.asciidoc +++ b/docs/api/upgrade-assistant.asciidoc @@ -1,15 +1,15 @@ [role="xpack"] [[upgrade-assistant-api]] -== Upgrade Assistant API +== Upgrade assistant APIs -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are currently experimental."] +Check the upgrade status of your Elasticsearch cluster and reindex indices that were created in the previous major version. The assistant helps you prepare for the next major version of Elasticsearch. -The Upgrade Assistant API allows you to check the upgrade status of your Elasticsearch cluster -and reindex indices that were created in the previous major version. The assistant helps you prepare -for the next major version of Elasticsearch. - -* <> -* <> +* <> +* <> +* <> +* <> include::upgrade-assistant/status.asciidoc[] include::upgrade-assistant/reindexing.asciidoc[] +include::upgrade-assistant/check_reindex_status.asciidoc[] +include::upgrade-assistant/cancel_reindex.asciidoc[] diff --git a/docs/api/upgrade-assistant/cancel_reindex.asciidoc b/docs/api/upgrade-assistant/cancel_reindex.asciidoc new file mode 100644 index 0000000000000..9f6755e46b547 --- /dev/null +++ b/docs/api/upgrade-assistant/cancel_reindex.asciidoc @@ -0,0 +1,32 @@ +[[cancel-reindex]] +=== Cancel reindex API +++++ +Cancel reindex +++++ + +Cancel reindexes that are waiting for the Elasticsearch reindex task to complete. For example, `lastCompletedStep` set to `40`. + +experimental[This API is *experimental* and may be changed or removed completely in a future release. The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are currently experimental.] + +[[cancel-reindex-request]] +==== Request + +`POST /api/upgrade_assistant/reindex/myIndex/cancel` + +[[cancel-reindex-response-codes]] +==== Response codes + +`200`:: + Indicates a successful call. + +[[cancel-reindex-status-example]] +==== Example + +The API returns the following: + +[source,js] +-------------------------------------------------- +{ + "acknowledged": true +} +-------------------------------------------------- diff --git a/docs/api/upgrade-assistant/check_reindex_status.asciidoc b/docs/api/upgrade-assistant/check_reindex_status.asciidoc new file mode 100644 index 0000000000000..da2b8d9d15d57 --- /dev/null +++ b/docs/api/upgrade-assistant/check_reindex_status.asciidoc @@ -0,0 +1,111 @@ +[[check-reindex-status]] +=== Check reindex status API +++++ +Check reindex status +++++ + +Check the status of the reindex operation. + +experimental[This API is *experimental* and may be changed or removed completely in a future release. The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are currently experimental.] + +[[check-reindex-status-request]] +==== Request + +`GET /api/upgrade_assistant/reindex/myIndex` + +[[check-reindex-status-response-codes]] +==== Response codes + +`200`:: + Indicates a successful call. + +[[check-reindex-status-example]] +==== Example + +The API returns the following: + +[source,js] +-------------------------------------------------- +{ + "reindexOp": { + "indexName": ".ml-state", + "newIndexName": ".reindexed-v7-ml-state", <1> + "status": 0, <2> + "lastCompletedStep": 40, <3> + "reindexTaskId": "QprwvTMzRQ2MLWOW22oQ4Q:11819", <4> + "reindexTaskPercComplete": 0.3, <5> + "errorMessage": null <6> + }, + "warnings": [], <7> + "hasRequiredPrivileges": true <8> +} +-------------------------------------------------- + +<1> Name of the new index that is being created. +<2> Current status of the reindex. For details, see <>. +<3> Last successfully completed step of the reindex. For details, see <> table. +<4> Task ID of the reindex task in Elasticsearch. Only present if reindexing has started. +<5> Percentage of how far the reindexing task in Elasticsearch has progressed, in decimal from from 0 to 1. +<6> Error that caused the reindex to fail, if it failed. +<7> An array of any warning codes explaining what changes are required for this reindex. For details, see <>. +<8> Specifies if the user has sufficient privileges to reindex this index. When security is unavailable or disables, returns `true`. + +[[status-code]] +==== Status codes + +`0`:: + In progress + +`1`:: + Completed + +`2`:: + Failed + +`3`:: + Paused +NOTE: If the {kib} node that started the reindex is shutdown or restarted, the reindex goes into a paused state after some time. +To resume the reindex, you must submit a new POST request to the `/api/upgrade_assistant/reindex/` endpoint. + +`4`:: + Cancelled + +[[step-code]] +==== Step codes + +`0`:: + The reindex operation has been created in Kibana. + +`10`:: + The index group services stopped. Only applies to some system indices. + +`20`:: + The index is set to `readonly`. + +`30`:: + The new destination index has been created. + +`40`:: + The reindex task in Elasticsearch has started. + +`50`:: + The reindex task in Elasticsearch has completed. + +`60`:: + Aliases were created to point to the new index, and the old index has been deleted. + +`70`:: + The index group services have resumed. Only applies to some system indices. + +[[warning-code]] +==== Warning codes + +`0`:: + Specifies to remove the `_all` meta field. + +`1`:: + Specifies to convert any coerced boolean values in the source document. For example, `yes`, `1`, and `off`. + +`2`:: + Specifies to convert documents to support Elastic Common Schema. Only applies to APM indices created in 6.x. + diff --git a/docs/api/upgrade-assistant/reindexing.asciidoc b/docs/api/upgrade-assistant/reindexing.asciidoc index b20960dc6dfe8..66561ab1739a8 100644 --- a/docs/api/upgrade-assistant/reindexing.asciidoc +++ b/docs/api/upgrade-assistant/reindexing.asciidoc @@ -1,154 +1,45 @@ -[[upgrade-assistant-api-reindexing]] -=== Reindex API +[[start-resume-reindex]] +=== Start or resume reindex API +++++ +Start or resume reindex +++++ -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are currently experimental."] +Start a new reindex or resume a paused reindex. -When checking the upgrade status, some indices will have the `reindex` paramaeter set to `true`. You can use this Reindexing API to reindex these indices. +experimental[This API is *experimental* and may be changed or removed completely in a future release. The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are currently experimental.] -==== Start or resume a reindex +[[start-resume-reindex-request]] +==== Request -===== Request +`POST /api/upgrade_assistant/reindex/myIndex` -To start a new reindex or resume a paused reindex, submit a POST request to the `/api/upgrade_assistant/reindex/` endpoint: +[[start-resume-reindex-codes]] +==== Response code -Note: You cannot access this endpoint via the Console in Kibana. +`200`:: + Indicates a successful call. -[source,js] --------------------------------------------------- -POST /api/upgrade_assistant/reindex/myIndex --------------------------------------------------- -// KIBANA +[[start-resume-reindex-example]] +==== Example -===== Response - -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- { "indexName": ".ml-state", - "newIndexName": ".reindexed-v7-ml-state", - "status": 0, - "lastCompletedStep": 0, - "reindexTaskId": null, - "reindexTaskPercComplete": null, - "errorMessage": null -} --------------------------------------------------- - -See the next section for an explanation of each field. - -==== Check the status of a reindex - -===== Request - -Once a reindex is started, you can check the status of the reindex operation by submitting a GET request to the `/api/upgrade_assistant/reindex/` endpoint: - -Note: You cannot access this endpoint via the Console in Kibana. - -[source,js] --------------------------------------------------- -GET /api/upgrade_assistant/reindex/myIndex --------------------------------------------------- -// KIBANA - -===== Response - -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: - -[source,js] --------------------------------------------------- -{ - "reindexOp": { - "indexName": ".ml-state", - "newIndexName": ".reindexed-v7-ml-state", <1> - "status": 0, <2> - "lastCompletedStep": 40, <3> - "reindexTaskId": "QprwvTMzRQ2MLWOW22oQ4Q:11819", <4> - "reindexTaskPercComplete": 0.3, <5> - "errorMessage": null <6> - }, - "warnings": [], <7> - "hasRequiredPrivileges": true <8> + "newIndexName": ".reindexed-v7-ml-state", <1> + "status": 0, <2> + "lastCompletedStep": 0, <3> + "reindexTaskId": null, <4> + "reindexTaskPercComplete": null, <5> + "errorMessage": null <6> } -------------------------------------------------- <1> Name of the new index that is being created. -<2> Current status of the reindex. See the <> for details. -<3> Last successfully completed step of the reindex. See the <> table for details. +<2> Current status of the reindex. For details, see <>. +<3> Last successfully completed step of the reindex. For details, see <> table. <4> Task ID of the reindex task in Elasticsearch. Only present if reindexing has started. <5> Percentage of how far the reindexing task in Elasticsearch has progressed, in decimal from from 0 to 1. <6> Error that caused the reindex to fail, if it failed. -<7> An array of any warning codes explaining what changes are required for this reindex. See the <> for details. -<8> Whether or not the current user has required privileges to reindex this index. Returns `true` if Security is not available or disabled. - -[[status-code]] -===== Status code - -The `status` field corresponds to these statuses: - -[horizontal] -0:: in progress -1:: completed -2:: failed -3:: paused -4:: cancelled - -[[step-code]] -===== Step code - -The `lastCompletedStep` field corresponds to these steps: - -[horizontal] -0:: The reindex operation has been created in Kibana. -10:: Index group services stopped. Only applies to some system indices. -20:: index set to readonly -30:: The new destination index has been created. -40:: The reindex task in Elasticsearch has started. -50:: The reindex task in Elasticsearch has completed. -60:: Aliases have been created to point to the new index, and the old index has been deleted. -70:: Index group services have been resumed. Only applies to some system indices. - -[[warning-code]] -===== Warning code - -The `warnings` field corresponds to an array of integers for these warnings: - -[horizontal] -0:: The `_all` meta field will be removed. -1:: Any coerced boolean values will be converted in the source document (example: `yes`, `1`, `off`). -2:: Documents will be converted to support Elastic Common Schema. Only applies to APM indices created in 6.x. - -===== Paused reindexes - -If the Kibana node that started the reindex is shutdown or restarted, the reindex will go into a paused state after some time. -To resume the reindex, you must submit a new POST request to the `/api/upgrade_assistant/reindex/` endpoint. - -==== Cancel a reindex - -===== Request - -You can cancel reindexes that are waiting for the Elasticsearch reindex task to complete (`lastCompletedStep` set to `40`). -To cancel a reindex, submit a POST request to the `/api/upgrade_assistant/reindex//cancel` endpoint: - -Note: You cannot access this endpoint via the Console in Kibana. - -[source,js] --------------------------------------------------- -POST /api/upgrade_assistant/reindex/myIndex/cancel --------------------------------------------------- -// KIBANA - -===== Response - -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: - -[source,js] --------------------------------------------------- -{ - "acknowledged": true -} --------------------------------------------------- diff --git a/docs/api/upgrade-assistant/status.asciidoc b/docs/api/upgrade-assistant/status.asciidoc index e4e50570b5c3f..2e99d549bd460 100644 --- a/docs/api/upgrade-assistant/status.asciidoc +++ b/docs/api/upgrade-assistant/status.asciidoc @@ -1,24 +1,28 @@ [[upgrade-assistant-api-status]] -=== Upgrade Readiness Status +=== Upgrade readiness status API +++++ +Upgrade readiness status +++++ -experimental["This API is *experimental* and may be changed or removed completely in a future release. The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are currently experimental."] +Check the status of your cluster. +experimental[This API is *experimental* and may be changed or removed completely in a future release. The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are currently experimental.] + +[[upgrade-assistant-api-status-request]] ==== Request -To check the status of your cluster, submit a GET request to the `/api/upgrade_assistant/status` endpoint: +`GET /api/upgrade_assistant/status` -Note: You cannot access this endpoint via the Console in Kibana. +[[upgrade-assistant-api-status-response-codes]] +==== Response codes -[source,js] --------------------------------------------------- -GET /api/upgrade_assistant/status --------------------------------------------------- -// KIBANA +`200`:: + Indicates a successful call. -==== Response +[[upgrade-assistant-api-status-example]] +==== Example -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following: [source,js] -------------------------------------------------- @@ -45,4 +49,4 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -<1> You can fix indices with the `reindex` attribute set to `true` using the <>. +<1> To fix indices with the `reindex` attribute, set to `true` using the <>. diff --git a/docs/api/url-shortening.asciidoc b/docs/api/url-shortening.asciidoc index 52da092831181..e98210e92d94a 100644 --- a/docs/api/url-shortening.asciidoc +++ b/docs/api/url-shortening.asciidoc @@ -1,13 +1,11 @@ [[url-shortening-api]] -== URL Shortening API +== URL shortening API -Kibana URLs contain the state of the application making them very long and cumbersome. -Internet Explorer has URL length restrictions, and some wiki and markup parsers don't do well with the full-length version of the Kibana URL. +{kib} URLs contain the state of the application, which makes them long and cumbersome. +Internet Explorer has URL length restrictions, and some wiki and markup parsers don't do well with the full-length version of the {kib} URL. -The short URLs enabled by this API are designed to make sharing Kibana URLs easier. +Short URLs are designed to make sharing {kib} URLs easier. -NOTE: You cannot access these endpoints via the Console in Kibana. - -* <> +* <> include::url_shortening/shorten_url.asciidoc[] diff --git a/docs/api/url_shortening/shorten_url.asciidoc b/docs/api/url_shortening/shorten_url.asciidoc index a13ed0e40e9bd..19d6234f13933 100644 --- a/docs/api/url_shortening/shorten_url.asciidoc +++ b/docs/api/url_shortening/shorten_url.asciidoc @@ -1,28 +1,37 @@ -[[url-shortening-api-api-shorten-url]] -=== Shorten URL +[[shorten-url-api]] +=== Shorten URL API +++++ +Shorten URL +++++ -The Shorten URL API allows for converting a Kibana URL into a token. +Convert a {kib} URL into a token. -Note: You cannot access this endpoint via the Console in Kibana. +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] +[[url-shortening-api-request]] ==== Request `POST /api/shorten_url` -==== Request Body +[[url-shortening-api-request-body]] +==== Request body -The request body must be a JSON object containing the following properties: - -`url` (required):: - (string) Kibana URL, relative to `/app/kibana`, to be shortened. +`url`:: + (Required, string) The {kib} URL that you want to shorten, Relative to `/app/kibana`. +[[url-shortening-api-response-body]] ==== Response body -The response body will have a top level `urlId` property that contains -the shortened URL token for the provided request body. +urlId:: A top level property that contains the shortened URL token for the provided request body. + +[[url-shortening-api-codes]] +==== Response code -==== Examples +`200`:: + Indicates a successful call. +[[url-shortening-api-example]] +==== Example [source,js] -------------------------------------------------- @@ -33,8 +42,7 @@ POST api/shorten_url -------------------------------------------------- // KIBANA -A successful call returns a response code of `200` and a response body -containing a JSON structure similar to the following example: +The API returns the following result: [source,js] -------------------------------------------------- @@ -43,6 +51,7 @@ containing a JSON structure similar to the following example: } -------------------------------------------------- -A shortened Kibana URL can then be constructed for easier sharing. +For easy sharing, construct the shortened {kib} URL: + `http://localhost:5601/goto/f73b295ff92718b26bc94edac766d8e3` diff --git a/docs/apm/agent-configuration.asciidoc b/docs/apm/agent-configuration.asciidoc index 2c408a5cc1e7e..4d2ae5d01688c 100644 --- a/docs/apm/agent-configuration.asciidoc +++ b/docs/apm/agent-configuration.asciidoc @@ -43,3 +43,8 @@ Adjusting the sampling rate controls what percent of requests are traced. `1.0` means _all_ requests are traced. If you set the `TRANSACTION_SAMPLE_RATE` to a value below `1.0`, the agent will randomly sample only a subset of transactions. Unsampled transactions only record the name of the transaction, the overall transaction time, and the result. + +IMPORTANT: In a distributed trace, the sampling decision is propagated by the initializing Agent. +This means if you're using multiple agents, only the originating service's sampling rate will be used. +Be sure to set sensible defaults in _all_ of your agents, especially the +{apm-rum-ref}/configuration.html#transaction-sample-rate[JavaScript RUM Agent]. diff --git a/docs/canvas.asciidoc b/docs/canvas.asciidoc deleted file mode 100644 index a25b528580b92..0000000000000 --- a/docs/canvas.asciidoc +++ /dev/null @@ -1,37 +0,0 @@ - -[role="xpack"] -[[canvas]] -= Canvas - -[partintro] --- - -Canvas is a data visualization and presentation tool that sits within Kibana. With Canvas, you can pull live data directly from Elasticsearch, and combine the data with colors, images, text, and your imagination to create dynamic, multi-page, pixel-perfect displays. If you are a little bit creative, a little bit technical, and a whole lot curious, then Canvas is for you. - -With Canvas, you can: - -* Create and personalize your work space with backgrounds, borders, colors, fonts, and more. - -* Customize your workpad with your own visualizations, such as images and text. - -* Customize your data by pulling it directly from Elasticsearch. - -* Show off your data with charts, graphs, progress monitors, and more. - -* Focus the data you want to display with filters. - -[role="screenshot"] -image::images/canvas-gs-example.png[] - -For a quick overview of Canvas, watch link:https://www.youtube.com/watch?v=ZqvF_5-1xjQ[Stand out with Canvas]. -//When https://github.com/elastic/Video/issues/358 is resolved, update this link. - --- - -include::canvas/canvas-getting-started.asciidoc[] - -include::canvas/canvas-workpad.asciidoc[] - -include::canvas/canvas-function-reference.asciidoc[] - -include::canvas/canvas-tinymath-functions.asciidoc[] diff --git a/docs/canvas/canvas-elements.asciidoc b/docs/canvas/canvas-elements.asciidoc new file mode 100644 index 0000000000000..c5c6f116ee34e --- /dev/null +++ b/docs/canvas/canvas-elements.asciidoc @@ -0,0 +1,268 @@ +[role="xpack"] +[[element-intro]] +== Showcase your data with elements + +Canvas _elements_ are the building blocks of your workpad. With elements, you can combine images, text, and visualizations to tell a story about your data. + +When you add elements to your workpad, you can: + +* <> + +* <> + +* <> + +* <> + +* <> + +[float] +[[add-canvas-element]] +=== Add elements to your workpad + +Choose the elements to display on your workpad, then familiarize yourself with the element using the preconfigured demo data. + +. Click *Add element*. + +. In the *Elements* window, select the element you want to use. ++ +[role="screenshot"] +image::images/canvas-element-select.gif[Canvas elements] + +. Play around with the default settings and see what the element can do. + +TIP: Want to use a different element? You can delete the element by selecting it, clicking the *Element options* icon in the top right corner, then selecting *Delete*. + +[float] +[[connect-element-data]] +=== Connect the element to your data + +When you are ready to move on from the demo data, connect the element to your own data. + +. Make sure that the element is selected, then select *Data*. + +. Click *Change your data source*. + +[float] +[[elasticsearch-sql-data-source]] +==== Connect to Elasticsearch SQL + +Access your data in Elasticsearch using the Elasticsearch SQL syntax. + +Unfamiliar with writing Elasticsearch SQL queries? For more information, refer to {ref}/sql-spec.html[SQL language]. + +. Click *Elasticsearch SQL*. + +. In the *Elasticearch SQL query* box, enter your query, then *Preview* it. + +. If everything looks correct, *Save* it. + +[float] +[[elasticsearch-raw-doc-data-source]] +==== Connect to Elasticsearch raw data + +Use the Lucene query syntax to use your raw data in Elasticsearch. + +For for more information about the Lucene query string sytax, refer to <>. + +. Click *Elasticsearch raw documents*. + +. In the *Index* field, enter the index pattern that you want to display. + +. From the *Fields* dropdown, select the associated fields you want to display. + +. To sort the data, select an option from the *Sort Field* and *Sort Order* dropdowns. + +. For more targeted queries, enter a *Query* using the Lucene query string syntax. + +. *Preview* the query. + +. If your query looks correct, *Save* it. + +[float] +[[timelion-data-source]] +==== Connect to Timelion + +Use <> queries to use your time series data. + +. Click *Timelion*. + +. Enter a *Query* using the Lucene query string syntax. ++ +For for more information about the Lucene query string syntax, refer to <>. + +. Enter the *Interval*, then *Preview* the query. + +. If your query looks correct, *Save* it. + +[float] +[[configure-display-options]] +=== Choose the display options + +Choose how you want the elements to appear on your workpad. + +[float] +[[data-display]] +==== Specify how to display the data + +When you connect your element to a data source, the element often appears as a warning. To remove the error, specify the display options. + +. Click *Display* + +. Change the display options for the element. + +[float] +[[element-display-container]] +==== Change the appearance of the element container + +Further define the appearance of the element container and border. + +. Next to *Element style*, click *+*, then select *Container style*. + +. Expand *Container style*. + +. Change the *Appearance* and *Border* options. + +[float] +[[apply-element-styles]] +==== Apply a set of styles + +To make your element look exactly the way you want, apply CSS overrides. + +. Next to *Element style*, click *+*, then select *CSS*. + +. Enter the *CSS*. For example, to center the Markdown element, enter: ++ +[source,js] +-------------------------------------------------- +.canvasRenderEl h1 { +text.align: center; +} +-------------------------------------------------- + +. Click *Apply stylesheet*. + +[float] +[[configure-auto-refresh-interval]] +==== Change the data auto-refresh interval + +Increase or decrease how often your data refreshes on your workpad. + +. In the top left corner, click the *Control settings* icon. + +. Under *Change auto-refresh interval*, select the interval you want to use. ++ +[role="screenshot"] +image::images/canvas-refresh-interval.png[Element data refresh interval] + +TIP: To manually refresh the data, click the *Refresh data* icon. + +[float] +[[organize-element]] +=== Organize the elements on your workpad + +Choose where you want the elements to appear on your workpad. + +[float] +[[move-canvas-elements]] +==== Move elements + +Move the element to a preferred location on your workpad. As you move the element, notice the alignment lines that appear to help you place the element exactly where you want it. + +* Click and drag the element to your preferred location. + +* To move the element by 1 pixel, select the element, press and hold Shift, then use your arrow keys. + +* To move the element by 10 pixels, select the element, then use your arrow keys. + +[float] +[[resize-canvas-elements]] +==== Resize elements + +Make your elements bigger or smaller than the default size. + +. Select the element. + +. Click and drag the resize handles to the size you want. + +[float] +[[align-canvas-elements]] +==== Align elements + +Align two or more elements on your workpad. + +. Press and hold Shift, then select the elements you want to align. + +. Click the *Element options* icon in the top right corner, then select *Align elements*. + +. From the *Alignment* menu, select how you want to align the elements on the workpad. ++ +[role="screenshot"] +image::images/canvas-align-elements.gif[Align elements] + +[float] +[[distribute-canvas-elements]] +==== Distribute elements + +Distribute three or more elements on your workpad. + +. Press and hold Shift, then select the elements you want to distribute. + +. Click the *Element options* icon in the top right corner, then select *Distribute elements*. + +. From the *Distribution* menu, select how you want to distribute the elements on the workpad. ++ +[role="screenshot"] +image::images/canvas-distribute-elements.gif[Distribute elements] + +[float] +[[change-element-order]] +==== Change the element order + +Change the order of how the elements are displayed on your workpad. + +. Select an element. + +. In the top right corder, click the *Element options* icon. + +. Select *Order*, then select the order that you want the element to appear. + +[float] +[[zoom-in-out]] +=== Use the zoom options + +In the upper left corner, click the *Zoom controls* icon, then select one of the options. + +[role="screenshot"] +image::images/canvas-zoom-controls.png[Zoom controls] + +[float] +[[element-save]] +=== Save elements + +After you have made changes to elements, save them so that you can reuse them across all of your workpads. + +. Select the element that you want to save. ++ +To save a group of elements, press and hold Shift, then select the elements you want to save. + +. Click the *Save as new element* icon. + +. In the *Create new element* window, enter a *Name*. + +. Enter an optional *Description*, then click *Save*. + +. To access the element, click *Add element*, then select *My elements*. + +[float] +[[add-more-pages]] +=== Add pages + +When you have run out of room on your workpad page, add more pages. + +. Click *Page 1*, then click *+*. + +. On the *Page* editor panel on the right, select the page transition from the *Transition* dropdown. ++ +[role="screenshot"] +image::images/canvas-add-pages.gif[Add pages] diff --git a/docs/canvas/canvas-expressions.asciidoc b/docs/canvas/canvas-expressions.asciidoc new file mode 100644 index 0000000000000..0fcc69c6db726 --- /dev/null +++ b/docs/canvas/canvas-expressions.asciidoc @@ -0,0 +1,39 @@ +[[canvas-expression-editor]] +=== Customize your element with the expression editor + +Each element is backed by an expression that represents the element style and data. To further define the appearance and behavior of the element, use the expression editor. + +. In the lower right corner, click *Expression editor*. + +. Edit the style and data parts of the expression that you want to change. + +. Click *Run*. + +. If you like what you see, click *Close*. + +For information about the Canvas expression language, see <>. + +//Insert expression video. + +[float] +[[canvas-expression-editor-example]] +=== Example: Using the expression editor + +Build a complex element using expressions. + +``` +image mode="contain" dataurl={ +asset { +filters | essql +query="SELECT host,response +FROM kibana_sample_data_logs +WHERE host='artifacts.elastic.co' +ORDER BY timestamp DESC +LIMIT 1"| +alterColumn "response" type="number" | +getCell "response" | +if {compare lt to=400} then="asset-0a807073-d056-4c7b-9bf4-225b71e47243" else="asset-1343672d-7c02-4402-929e-0f8fef69cddd" +} +} | render + +``` \ No newline at end of file diff --git a/docs/canvas/canvas-getting-started.asciidoc b/docs/canvas/canvas-getting-started.asciidoc deleted file mode 100644 index 3874b91b85e92..0000000000000 --- a/docs/canvas/canvas-getting-started.asciidoc +++ /dev/null @@ -1,162 +0,0 @@ -[role="xpack"] -[[canvas-getting-started]] -== Getting started with Canvas - -To get up and running with Canvas, use the following tutorial where you'll create a display for monitoring sales at an eCommerce store. - -[float] -=== Before you begin - -For this tutorial, you'll need to add the <>. - -[float] -=== Create and personalize your workpad - -Your first step to working with Canvas is to create a workpad. - -. Open *Canvas*. - -. Click *Create workpad*. - -. To add a *Name* for your workpad, use the editor on the right. For example, `My Canvas Workpad`. - -[float] -=== Customize your workpad with images - -To customize your workpad to look the way you want, add your own images. - -. Click *Add element*, then click *Image*. -+ -The default Elastic logo image appears on your page. - -. To replace the Elastic logo with your own image, select the image, then use the editor on the right. - -. To move the image, click and drag it to your preferred location. - -[role="screenshot"] -image::images/canvas-image-element.png[] - -You'll notice that the image is tagged as an asset, which allows you to reuse the image from *Manage assets*. - -TIP: Want to delete an element? Select the element, then press the delete button on your keyboard. - -[float] -=== Customize your data with metrics - -Customize your data by connecting it to the Sample eCommerce orders data. - -. Click *Add element*, then click *Metric*. -+ -By default, the *Metric* element is connected to a demo data source, which enables you to experiment with the element before you connect it to your own data source. - -. To connect the element to your own data source, make sure that the element is selected, then click *Data*. - -.. Click *Change your data source*, then click *Elasticsearch SQL*. - -.. In the *Elasticsearch SQL query* field, enter the following query: -+ -`SELECT sum(taxless_total_price) AS sum_total_price FROM "kibana_sample_data_ecommerce"` -+ -The query selects the total price field and sets it to the sum_total_price field. These fields are pulled from the kibana_sample_data_ecommerce index that you installed. - -.. To verify that the data is correct, click *Preview*. If you like what you see, click *Save*. -+ -At this point, the element displays an error. - -. Specify how to process and display the data. - -.. Click *Display* - -.. Under *Number*, select *Value* from the function drop-down list, then select *sum_total_price* from the column drop-down list. - -.. Change the *Label* to `Total sales`. -+ -You'll notice that the error is gone, but the number could use some formatting. - -. To format the number, use the Canvas expression language. - -.. In the lower right corner, click *Expression editor*. -+ -You're now looking at the raw data syntax that Canvas uses to display the element. - -.. Look for `math "sum_total_price"`, then add `| formatNumber "$0a"`. - -.. To update the number, click *Run*. - -[role="screenshot"] -image::images/canvas-metric-element.png[] - -[float] -=== Show off your data with charts - -To show what your data can do, add charts, graphs, progress monitors, and more to your workpad. - -. Click *Add element*, then click *Area chart*. - -. To connect the element to your own data source, make sure that the element is selected, then click *Data*. - -.. Click *Change your data source*, then click *Elasticsearch SQL*. - -.. To obtain the taxless total price by date, enter the following into the *Elasticsearch SQL query* field: -+ -`SELECT order_date, taxless_total_price FROM "kibana_sample_data_ecommerce" ORDER BY order_date` -+ -Although you used the Elasticsearch SQL data source for the metric and area chart elements, each element can display a different data source. Pages and workpads often contain multiple data sources. - -.. To verify that the data is correct, click *Preview*. If you like what you see, click *Save*. - -. Specify how to display the data. - -.. Click *Display* - -.. From the *X-axis* drop-down lists, select *Value*, then select *order_date*. - -.. From the *Y-axis* drop-down lists, select *Value*, then select *taxless_total_price*. - -[role="screenshot"] -image::images/canvas-chart-element.png[] - -[float] -=== Show how your data changes over time - -To focus your data on a specific time range, add a time filter to your workpad. - -. Click *Add element*, then click *Time filter*. - -. Specify how to display the data. - -.. Click *Display* - -.. 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[] - -To see how the data changes, set the time filter to *Last 7 days*. As you change the time filter options, the metrics dynamically update. - -Your workpad is now complete! Use the icons in the upper left corner to: - -* Display your workpad in fullscreen mode - -* Download your workpad as a PDF report or JSON object - -* Configure the refresh rate for your data - -* Share your workpad - -[float] -=== Next steps -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]. - -//* Learn more about: - -//** {kibana-ref}/canvas-workpad[Workpads] -//** Assets -//** Data sources -//** Elements - -* Deep dive into the {kibana-ref}/canvas-function-reference.html[expression language and functions] that drive Canvas. diff --git a/docs/canvas/canvas-present-workpad.asciidoc b/docs/canvas/canvas-present-workpad.asciidoc new file mode 100644 index 0000000000000..21b112f68eb69 --- /dev/null +++ b/docs/canvas/canvas-present-workpad.asciidoc @@ -0,0 +1,27 @@ +[role="xpack"] +[[canvas-present-workpad]] +== Present your workpad + +When you are ready to present your workpad, use and enable the presentation options. + +[float] +[[view-fullscreen-mode]] +=== View your workpad in fullscreen mode + +In the upper left corner, click the *Enter fullscreen mode* icon. + +[role="screenshot"] +image::images/canvas-fullscreen.png[Fullscreen mode] + +[float] +[[enable-autoplay]] +=== Enable autoplay + +Automatically cycle through your workpads pages in fullscreen mode. + +. In the upper left corner, click the *Control settings* icon. + +. Under *Change cycling interval*, select the interval you want to use. ++ +[role="screenshot"] +image::images/canvas-refresh-interval.png[Element data refresh interval] diff --git a/docs/canvas/canvas-share-workpad.asciidoc b/docs/canvas/canvas-share-workpad.asciidoc new file mode 100644 index 0000000000000..5cc5b953e5775 --- /dev/null +++ b/docs/canvas/canvas-share-workpad.asciidoc @@ -0,0 +1,48 @@ +[role="xpack"] +[[workpad-share-options]] +== Share your workpad + +When you are ready to share your workpad, create a PDF, or export your workpad. + +[float] +[[create-workpad-pdf]] +=== Create a PDF + +To view your workpad outside of Kibana, generate a PDF. + +. If you are using a Gold or Platinum license, enable reporting in your `config/kibana.yml` file. + +. From your workpad, click the *Share workpad* icon in the upper left corner, then select *PDF reports*. + +. Click *Generate PDF*. ++ +[role="screenshot"] +image::images/canvas-generate-pdf.gif[Generate PDF] + +[float] +[[export-workpad]] +=== Export your workpad + +To share your workpad with another author, export it as a JSON file. + +[float] +[[export-single-workpad]] +==== Export a single workpad + +. From your workpad, click the *Share workpad* icon in the upper left corner. + +. Select *Download as JSON*. ++ +[role="screenshot"] +image::images/canvas-export-workpad.png[Export single workpad] + +[float] +[[export-multiple-workpads]] +==== Export multiple workpads + +. Go to the *Canvas workpads* page. + +. Select the workpads you want to export + +. Click *Export*. + diff --git a/docs/canvas/canvas-tutorial.asciidoc b/docs/canvas/canvas-tutorial.asciidoc new file mode 100644 index 0000000000000..efc03f1c6c494 --- /dev/null +++ b/docs/canvas/canvas-tutorial.asciidoc @@ -0,0 +1,157 @@ +[role="xpack"] +[[canvas-tutorial]] +== Canvas tutorial + +To get up and running with Canvas, use the following tutorial where you'll create a display for monitoring sales at an eCommerce store. + +[float] +=== Before you begin + +For this tutorial, you'll need to add the <>. + +[float] +=== Create and personalize your workpad + +Your first step to working with Canvas is to create a workpad. + +. Open *Canvas*. + +. Click *Create workpad*. + +. To add a *Name* for your workpad, use the editor on the right. For example, `My Canvas Workpad`. + +[float] +=== Customize your workpad with images + +To customize your workpad to look the way you want, add your own images. + +. Click *Add element*, then click *Image*. ++ +The default Elastic logo image appears on your page. + +. To replace the Elastic logo with your own image, select the image, then use the editor on the right. + +. To move the image, click and drag it to your preferred location. + +[role="screenshot"] +image::images/canvas-image-element.png[] + +You'll notice that the image is tagged as an asset, which allows you to reuse the image from *Manage assets*. + +[float] +=== Customize your data with metrics + +Customize your data by connecting it to the Sample eCommerce orders data. + +. Click *Add element*, then click *Metric*. ++ +By default, the *Metric* element is connected to a demo data source, which enables you to experiment with the element before you connect it to your own data source. + +. To connect the element to your own data source, make sure that the element is selected, then click *Data*. + +.. Click *Change your data source*, then click *Elasticsearch SQL*. + +.. In the *Elasticsearch SQL query* field, enter the following query: ++ +`SELECT sum(taxless_total_price) AS sum_total_price FROM "kibana_sample_data_ecommerce"` ++ +The query selects the total price field and sets it to the sum_total_price field. These fields are pulled from the kibana_sample_data_ecommerce index that you installed. + +.. To verify that the data is correct, click *Preview*. If you like what you see, click *Save*. ++ +At this point, the element displays an error. + +. Specify how to process and display the data. + +.. Click *Display* + +.. Under *Number*, select *Value* from the function drop-down list, then select *sum_total_price* from the column drop-down list. + +.. Change the *Label* to `Total sales`. ++ +You'll notice that the error is gone, but the number could use some formatting. + +. To format the number, use the Canvas expression language. + +.. In the lower right corner, click *Expression editor*. ++ +You're now looking at the raw data syntax that Canvas uses to display the element. + +.. Look for `math "sum_total_price"`, then add `| formatNumber "$0a"`. + +.. To update the number, click *Run*. + +[role="screenshot"] +image::images/canvas-metric-element.png[] + +[float] +=== Show off your data with charts + +To show what your data can do, add charts, graphs, progress monitors, and more to your workpad. + +. Click *Add element*, then click *Area chart*. + +. To connect the element to your own data source, make sure that the element is selected, then click *Data*. + +.. Click *Change your data source*, then click *Elasticsearch SQL*. + +.. To obtain the taxless total price by date, enter the following into the *Elasticsearch SQL query* field: ++ +`SELECT order_date, taxless_total_price FROM "kibana_sample_data_ecommerce" ORDER BY order_date` ++ +Although you used the Elasticsearch SQL data source for the metric and area chart elements, each element can display a different data source. Pages and workpads often contain multiple data sources. + +.. To verify that the data is correct, click *Preview*. If you like what you see, click *Save*. + +. Specify how to display the data. + +.. Click *Display* + +.. From the *X-axis* drop-down lists, select *Value*, then select *order_date*. + +.. From the *Y-axis* drop-down lists, select *Value*, then select *taxless_total_price*. + +[role="screenshot"] +image::images/canvas-chart-element.png[] + +[float] +=== Show how your data changes over time + +To focus your data on a specific time range, add a time filter to your workpad. + +. Click *Add element*, then click *Time filter*. + +. Specify how to display the data. + +.. Click *Display* + +.. 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[] + +To see how the data changes, set the time filter to *Last 7 days*. As you change the time filter options, the metrics dynamically update. + +Your workpad is now complete! Use the icons in the upper left corner to: + +* Display your workpad in fullscreen mode + +* Download your workpad as a PDF report or JSON object + +* Configure the refresh rate for your data + +* Share your workpad + +[float] +=== Next steps +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]. + +* Learn more about <>. + +* Learn more about <>. + +* Deep dive into the {kibana-ref}/canvas-function-reference.html[expression language and functions] that drive Canvas. diff --git a/docs/canvas/canvas-workpad.asciidoc b/docs/canvas/canvas-workpad.asciidoc index 87df4ddb7537f..f664f055a5ff6 100644 --- a/docs/canvas/canvas-workpad.asciidoc +++ b/docs/canvas/canvas-workpad.asciidoc @@ -1,72 +1,93 @@ [role="xpack"] -[[canvas-workpad]] -=== Create a workpad +[[create-canvas-workpad]] +== Create a workpad -When you create a workpad, you'll start with a blank page, or you can choose a workpad that is already started for you. +A Canvas _workpad_ provides you with a workspace where you can build presentations of your live data. -. Open *Canvas*. +To create a workpad, you can: -. Choose one of the following options: +* <> -* To start with a single, blank workpad, click *Create workpad*. +* <> -* To create a workpad from a template, select *Templates*, then select a preconfigured template. +* <> -* To import an existing workpad, click and drag a workpad JSON file to the *Import workpad JSON file* field. +* <> -For advanced workpad examples, add a <>, then select *Canvas* from the *View Data* dropdown list. +[float] +[[blank-canvas-workpad]] +=== Start with a blank page -For more workpad inspiration, go to the link:https://www.elastic.co/blog/[Elastic Blog]. +To use the background colors, images, and data of your choice, start with a blank workpad. -[float] -=== Personalize your workpad +. Open *Canvas*. -To personalize your workpad, use the editor on the right. +. On the *Canvas workpads* page, click *Create workpad*. -. Add a *Name* to your workpad, for example, `My Canvas Workpad`. +. Add a *Name* to your workpad. -. In the *Width* and *Height* fields, specify the size of your workpad. +. In the *Width* and *Height* fields, specify the size. -. Select the layout for your workpad. +. Select the layout. + For example, click *720p* for a traditional presentation layout. . Click the *Background color* picker, then select the background color for your workpad. + -image::images/canvas-background-color-picker.gif[] +[role="screenshot"] +image::images/canvas-background-color-picker.gif[Canvas color picker] -. If you already know that you want to apply styles to the entire workpad, use the *Global CCS overrides*. +[float] +[[canvas-template-workpad]] +=== Create a workpad from a template + +If you're unsure about where to start, you can use one of the preconfigured templates that come with Canvas. -.. Expand *Global CCS overrides*. +. Open *Canvas*. -.. Enter the CCS, then click *Apply stylesheet*. +. On the *Canvas workpads* page, select *Templates*. -[float] -=== Share your workpad +. Click the preconfigured template that you want to use. -When you are ready to share your workpad, create a PDF, or export your workpad to another author. +. Add your own *Name* to the workpad. [float] -==== Create a PDF of your workpad +[[import-canvas-workpad]] +=== Import an existing workpad -To view your workpad outside of Kibana, generate a PDF. +When you want to use a workpad that someone else has already started, import the JSON file into Canvas. -. If you are using a basic license, enable reporting in your `config/kibana.yml` file. +. Open *Canvas*. + +. On the *Canvas workpads* page, click and drag the file to the *Import workpad JSON file* field. + +[float] +[[sample-data-workpad]] +=== Use a sample data workpad -. From your workpad, click the *Share workpad* icon in the upper left corner, then select *PDF reports*. +Each of the sample data sets comes with a Canvas workpad that you can use for your own workpad inspiration. -. Click *Generate PDF*. +. Add a {kibana-ref}/add-sample-data.html[sample data set]. + +. On the *Add Data to Kibana* page, click the *View data* dropdown list, then select *Canvas*. + -image::images/canvas-generate-pdf.gif[] +Need some more workpad inspiration? Check out the link:https://www.elastic.co/blog/[Elastic Blog]. [float] -==== Export your workpad - -To share your workpads with another author, export your workpads as JSON files. +[[apply-workpad-styles]] +== Apply a set of styles to the entire workpad -. Go to the *Canvas workpads* page. +To make your workpad look exactly the way you want, use the editor on the right to apply CSS overrides. -. Choose one of the following options: -* To export a single workpad, click the *Export* icon next to the workpad you want to export. +. Expand *Global CSS overrides*. -* To export multiple workpads, select the workpads you want to export, then click *Export*. \ No newline at end of file +. Enter the CSS. For example, to change the background on every page, enter: ++ +[source,js] +-------------------------------------------------- +.canvasPage { +background-color: #3990e6; +} +-------------------------------------------------- + +. Click *Apply stylesheet*. diff --git a/docs/code/code-basic-nav.asciidoc b/docs/code/code-basic-nav.asciidoc index 77a56b24801cc..ccd290532b669 100644 --- a/docs/code/code-basic-nav.asciidoc +++ b/docs/code/code-basic-nav.asciidoc @@ -19,7 +19,7 @@ image::images/code-blame.png[] [float] ==== Branch selector -You can use the Branch selector to view different branches of a repo. Note that code intelligence and search index are not available for any branch other than master branch. +You can use the Branch selector to view different branches of a repo. Note that code intelligence and search index are not available for any branch other than the master branch. include::code-semantic-nav.asciidoc[] diff --git a/docs/code/code-getting-started.asciidoc b/docs/code/code-getting-started.asciidoc index ec279238c6dc2..e5a2f98abf876 100644 --- a/docs/code/code-getting-started.asciidoc +++ b/docs/code/code-getting-started.asciidoc @@ -1,7 +1,7 @@ [[code-getting-started]] == Getting Started with Code -The easiest way to get started with *Code* is to simply import a real-world repository. +The easiest way to get started with *Code* is to import a real-world repository. [float] ==== Before you begin @@ -11,7 +11,8 @@ If you are in an environment where you have multiple {kib} instances in a cluste [float] ==== Enable Code app -In beta, Code needs to be turned on by adding the following line to `kibana.yaml` +While in beta, you can turn on *Code* by adding the following line to `kibana.yaml`: + [source,yaml] ---- xpack.code.ui.enabled: true @@ -19,7 +20,7 @@ xpack.code.ui.enabled: true [float] ==== Import your first repository -. Navigate to the Code app. +. In {Kib}, navigate to *Code*. . In the *Repository URL* field, paste the following GitHub clone URL: + @@ -28,6 +29,8 @@ xpack.code.ui.enabled: true https://github.com/Microsoft/TypeScript-Node-Starter ---- +`https` is recommend for cloning git repositories. + . Click *Import*. + A new item in the list displays the cloning and indexing progress of the `TypeScript-Node-Starter` repo. diff --git a/docs/code/code-install-lang-server.asciidoc b/docs/code/code-install-lang-server.asciidoc index 1bb5a24f0c7f3..ba50cfd8de323 100644 --- a/docs/code/code-install-lang-server.asciidoc +++ b/docs/code/code-install-lang-server.asciidoc @@ -6,11 +6,9 @@ [role="screenshot"] image::images/code-lang-server-tab.png[] -The following languages are supported for the current version: +For the current version, *Code* supports the following languages in addition to TypeScript: -* Built-in language support: `TypeScript` - -* Additional language support: `Java` +* `Java` You can check the status of the language servers and get installation instructions on the *Language Servers* tab. Make sure the status of the language server is `INSTALLED` or `RUNNING` after you restart the {kib} instance. [role="screenshot"] diff --git a/docs/code/code-repo-management.asciidoc b/docs/code/code-repo-management.asciidoc index dde3c4dbc6fd1..e3ebd809f480d 100644 --- a/docs/code/code-repo-management.asciidoc +++ b/docs/code/code-repo-management.asciidoc @@ -23,10 +23,11 @@ In some cases you might need to manually refresh the index besides automatic ind ==== Clone URL management For security reasons, *Code* only allows the following hostnames in the git clone URL by default: -[source,yaml] ----- -['github.com', 'gitlab.com', 'bitbucket.org', 'gitbox.apache.org', 'eclipse.org'] ----- +- `github.com` +- `gitlab.com` +- `bitbucket.org` +- `gitbox.apache.org` +- `eclipse.org` You can add your own hostname (for example, acme.com) to the whitelist by adding the following line to your `config/kibana.yaml` file: diff --git a/docs/code/code-search.asciidoc b/docs/code/code-search.asciidoc index 777669be8139a..c3086bfb850a0 100644 --- a/docs/code/code-search.asciidoc +++ b/docs/code/code-search.asciidoc @@ -10,7 +10,7 @@ image::images/code-quick-search.png[] [float] ==== Full-text search -If the quick search results don’t contain what you are looking for, you can press ‘Enter’ to conduct a full text search. +If the quick search results don’t contain what you are looking for, you can press ‘Enter’ to conduct a full-text search. [role="screenshot"] image::images/code-full-text-search.png[] You can further refine the results by using the repo and language filters on the left. diff --git a/docs/code/code-semantic-nav.asciidoc b/docs/code/code-semantic-nav.asciidoc index c85c7e87fda54..a1535f1449dfe 100644 --- a/docs/code/code-semantic-nav.asciidoc +++ b/docs/code/code-semantic-nav.asciidoc @@ -1,15 +1,19 @@ [[code-semantic-nav]] == Semantic code navigation -If the file is one of *Code’s* <> and the corresponding language server is <>, you can navigate the files with semantic code navigation features. + +You can navigate a file with semantic code navigation features if: + +- *Code* supports the file's <> +- You have installed the corresponding <> [float] ==== Goto definition and find reference Hovering your cursor over a symbol in a file opens information about the symbol, including its qualified name and documentation, when available. You can perform two actions: -* *Goto Definition* navigates to the symbol definition. If the definition is defined in another repo, *Code* can find the definition if the definition repo is also imported. +* *Goto Definition* navigates to the symbol definition. Definitions defined in a different repo can be found, provided that you have imported the repo with the definition. -* *Find Reference* opens a panel that lists all the places where the symbol is referenced in the current repo. +* *Find Reference* opens a panel that lists all references to the symbol. [role="screenshot"] image::images/code-semantic-nav.png[] diff --git a/docs/code/index.asciidoc b/docs/code/index.asciidoc index 7e7350764793b..d29ac440d6e23 100644 --- a/docs/code/index.asciidoc +++ b/docs/code/index.asciidoc @@ -4,12 +4,16 @@ [partintro] -- -beta[] Interaction with source code is pervasive and essential for any technology company. Speed of innovation is limited by how easy it is to search, navigate, and gain insight into your source code. Elastic *Code* provides an easy-to-use code search solution that scales with your organization. *Code* empowers your team to ship awesome products and provide the best services. *Code* offers the following functions: +beta[] -* Jump to definition and find references for a symbol +Interaction with source code is pervasive and essential for any technology company. Speed of innovation is limited by how easy it is to search, navigate, and gain insight into your source code. +Elastic *Code* provides an easy-to-use code search solution that scales with your organization and empowers your team to understand your codebase faster than ever before. +*Code* offers the following functions: + +* Find references and definitions for any object or symbol * Typeahead search for symbol definition, file, and repo * Symbol table -* Full text search with repo and language filters +* Full-text search with repo and language filters <> with *Code* by importing your first repo. -- diff --git a/docs/dev-tools.asciidoc b/docs/dev-tools.asciidoc deleted file mode 100644 index ebd7e81b31cd2..0000000000000 --- a/docs/dev-tools.asciidoc +++ /dev/null @@ -1,21 +0,0 @@ - -[[devtools-kibana]] -= Dev Tools - -[partintro] --- -The *Dev Tools* page contains development tools that you can use to interact -with your data in Kibana. - -* <> -* <> -* <> - - --- - -include::dev-tools/console/console.asciidoc[] - -include::dev-tools/searchprofiler/index.asciidoc[] - -include::dev-tools/grokdebugger/index.asciidoc[] diff --git a/docs/development/add-data-guide.asciidoc b/docs/developer/add-data-guide.asciidoc similarity index 100% rename from docs/development/add-data-guide.asciidoc rename to docs/developer/add-data-guide.asciidoc diff --git a/docs/development/core-development.asciidoc b/docs/developer/core-development.asciidoc similarity index 100% rename from docs/development/core-development.asciidoc rename to docs/developer/core-development.asciidoc diff --git a/docs/development/core/development-basepath.asciidoc b/docs/developer/core/development-basepath.asciidoc similarity index 100% rename from docs/development/core/development-basepath.asciidoc rename to docs/developer/core/development-basepath.asciidoc diff --git a/docs/development/core/development-dependencies.asciidoc b/docs/developer/core/development-dependencies.asciidoc similarity index 100% rename from docs/development/core/development-dependencies.asciidoc rename to docs/developer/core/development-dependencies.asciidoc diff --git a/docs/development/core/development-elasticsearch.asciidoc b/docs/developer/core/development-elasticsearch.asciidoc similarity index 100% rename from docs/development/core/development-elasticsearch.asciidoc rename to docs/developer/core/development-elasticsearch.asciidoc diff --git a/docs/development/core/development-functional-tests.asciidoc b/docs/developer/core/development-functional-tests.asciidoc similarity index 100% rename from docs/development/core/development-functional-tests.asciidoc rename to docs/developer/core/development-functional-tests.asciidoc diff --git a/docs/development/core/development-modules.asciidoc b/docs/developer/core/development-modules.asciidoc similarity index 100% rename from docs/development/core/development-modules.asciidoc rename to docs/developer/core/development-modules.asciidoc diff --git a/docs/development/core/development-unit-tests.asciidoc b/docs/developer/core/development-unit-tests.asciidoc similarity index 100% rename from docs/development/core/development-unit-tests.asciidoc rename to docs/developer/core/development-unit-tests.asciidoc diff --git a/docs/developer/index.asciidoc b/docs/developer/index.asciidoc new file mode 100644 index 0000000000000..62858f56ce3a5 --- /dev/null +++ b/docs/developer/index.asciidoc @@ -0,0 +1,25 @@ +[[development]] += Developer guide + +[partintro] +-- +Contributing to Kibana can be daunting at first, but it doesn't have to be. If +you're planning a pull request to the Kibana repository, you may want to start +with <>. + +If you'd prefer to use Kibana's internal plugin API, then check out +<>. +-- + +include::core-development.asciidoc[] + +include::plugin-development.asciidoc[] + +include::visualize/development-visualize-index.asciidoc[] + +include::add-data-guide.asciidoc[] + +include::security/index.asciidoc[] + +include::pr-review.asciidoc[] + diff --git a/docs/development/plugin-development.asciidoc b/docs/developer/plugin-development.asciidoc similarity index 100% rename from docs/development/plugin-development.asciidoc rename to docs/developer/plugin-development.asciidoc diff --git a/docs/development/plugin/development-plugin-feature-registration.asciidoc b/docs/developer/plugin/development-plugin-feature-registration.asciidoc similarity index 81% rename from docs/development/plugin/development-plugin-feature-registration.asciidoc rename to docs/developer/plugin/development-plugin-feature-registration.asciidoc index 7505b018c6fbd..f9078440cff2b 100644 --- a/docs/development/plugin/development-plugin-feature-registration.asciidoc +++ b/docs/developer/plugin/development-plugin-feature-registration.asciidoc @@ -1,15 +1,15 @@ [[development-plugin-feature-registration]] === Plugin feature registration -If your plugin will be used with {kib}’s default distribution, then you have the ability to register the features that your plugin provides. Features are typically apps in {kib}; once registered, you can toggle them via Spaces, and secure them via Roles when security is enabled. +If your plugin will be used with {kib}'s default distribution, then you have the ability to register the features that your plugin provides. Features are typically apps in {kib}; once registered, you can toggle them via Spaces, and secure them via Roles when security is enabled. ==== UI Capabilities -Registering features also gives your plugin access to “UI Capabilities”. These capabilities are boolean flags that you can use to conditionally render your interface, based on the current user’s permissions. For example, you can hide or disable a Save button if the current user is not authorized. +Registering features also gives your plugin access to “UI Capabilities”. These capabilities are boolean flags that you can use to conditionally render your interface, based on the current user's permissions. For example, you can hide or disable a Save button if the current user is not authorized. ==== Registering a feature -Feature registration is controlled via the built-in `xpack_main` plugin. To register a feature, call `xpack_main`'s `registerFeature` function from your plugin’s `init` function, and provide the appropriate details: +Feature registration is controlled via the built-in `xpack_main` plugin. To register a feature, call `xpack_main`'s `registerFeature` function from your plugin's `init` function, and provide the appropriate details: ["source","javascript"] ----------- @@ -22,7 +22,7 @@ init(server) { ----------- ===== Feature details -Registering a feature consists of the following fields. For more information, consult the {repo}blob/{branch}/x-pack/legacy/plugins/xpack_main/server/lib/feature_registry/feature_registry.ts[feature registry interface]. +Registering a feature consists of the following fields. For more information, consult the {repo}blob/{branch}/x-pack/plugins/features/server/feature_registry.ts[feature registry interface]. [cols="1a, 1a, 1a, 1a"] @@ -42,10 +42,10 @@ Registering a feature consists of the following fields. For more information, co |`app` (required) |`string[]` |`["sample_app", "kibana"]` -|An array of applications this feature enables. Typically, all of your plugin’s apps (from `uiExports`) will be included here. +|An array of applications this feature enables. Typically, all of your plugin's apps (from `uiExports`) will be included here. |`privileges` (required) -|{repo}blob/{branch}/x-pack/legacy/plugins/xpack_main/server/lib/feature_registry/feature_registry.ts[`FeatureWithAllOrReadPrivileges`]. +|{repo}blob/{branch}/x-pack/plugins/features/server/feature.ts[`FeatureWithAllOrReadPrivileges`]. |see examples below |The set of privileges this feature requires to function. @@ -63,7 +63,7 @@ Registering a feature consists of the following fields. For more information, co ===== Privilege definition The `privileges` section of feature registration allows plugins to implement read/write and read-only modes for their applications. -For a full explanation of fields and options, consult the {repo}blob/{branch}/x-pack/legacy/plugins/xpack_main/server/lib/feature_registry/feature_registry.ts[feature registry interface]. +For a full explanation of fields and options, consult the {repo}blob/{branch}/x-pack/plugins/features/server/feature_registry.ts[feature registry interface]. ==== Using UI Capabilities @@ -72,7 +72,7 @@ To access capabilities, import them from `ui/capabilities`: ["source","javascript"] ----------- -import { uiCapabilities } from ‘ui/capabilities’; +import { uiCapabilities } from 'ui/capabilities'; const canUserSave = uiCapabilities.foo.save; if (canUserSave) { @@ -124,7 +124,7 @@ The `all` privilege defines a single “save” UI Capability. To access this in ["source","javascript"] ----------- -import { uiCapabilities } from ‘ui/capabilities’; +import { uiCapabilities } from 'ui/capabilities'; const canUserSave = uiCapabilities.canvas.save; if (canUserSave) { @@ -142,7 +142,7 @@ init(server) { const xpackMainPlugin = server.plugins.xpack_main; xpackMainPlugin.registerFeature({ id: 'dev_tools', - name: i18n.translate('xpack.main.featureRegistry.devToolsFeatureName', { + name: i18n.translate('xpack.features.devToolsFeatureName', { defaultMessage: 'Dev Tools', }), icon: 'devToolsApp', @@ -167,7 +167,7 @@ init(server) { ui: ['show'], }, }, - privilegesTooltip: i18n.translate('xpack.main.featureRegistry.devToolsPrivilegesTooltip', { + privilegesTooltip: i18n.translate('xpack.features.devToolsPrivilegesTooltip', { defaultMessage: 'User should also be granted the appropriate Elasticsearch cluster and index privileges', }), diff --git a/docs/development/plugin/development-plugin-functional-tests.asciidoc b/docs/developer/plugin/development-plugin-functional-tests.asciidoc similarity index 100% rename from docs/development/plugin/development-plugin-functional-tests.asciidoc rename to docs/developer/plugin/development-plugin-functional-tests.asciidoc diff --git a/docs/development/plugin/development-plugin-localization.asciidoc b/docs/developer/plugin/development-plugin-localization.asciidoc similarity index 100% rename from docs/development/plugin/development-plugin-localization.asciidoc rename to docs/developer/plugin/development-plugin-localization.asciidoc diff --git a/docs/development/plugin/development-plugin-resources.asciidoc b/docs/developer/plugin/development-plugin-resources.asciidoc similarity index 100% rename from docs/development/plugin/development-plugin-resources.asciidoc rename to docs/developer/plugin/development-plugin-resources.asciidoc diff --git a/docs/development/plugin/development-uiexports.asciidoc b/docs/developer/plugin/development-uiexports.asciidoc similarity index 100% rename from docs/development/plugin/development-uiexports.asciidoc rename to docs/developer/plugin/development-uiexports.asciidoc diff --git a/docs/development/pr-review.asciidoc b/docs/developer/pr-review.asciidoc similarity index 100% rename from docs/development/pr-review.asciidoc rename to docs/developer/pr-review.asciidoc diff --git a/docs/development/security/index.asciidoc b/docs/developer/security/index.asciidoc similarity index 100% rename from docs/development/security/index.asciidoc rename to docs/developer/security/index.asciidoc diff --git a/docs/development/security/rbac.asciidoc b/docs/developer/security/rbac.asciidoc similarity index 100% rename from docs/development/security/rbac.asciidoc rename to docs/developer/security/rbac.asciidoc diff --git a/docs/development/visualize/development-create-visualization.asciidoc b/docs/developer/visualize/development-create-visualization.asciidoc similarity index 100% rename from docs/development/visualize/development-create-visualization.asciidoc rename to docs/developer/visualize/development-create-visualization.asciidoc diff --git a/docs/development/visualize/development-embedding-visualizations.asciidoc b/docs/developer/visualize/development-embedding-visualizations.asciidoc similarity index 100% rename from docs/development/visualize/development-embedding-visualizations.asciidoc rename to docs/developer/visualize/development-embedding-visualizations.asciidoc diff --git a/docs/development/visualize/development-visualize-index.asciidoc b/docs/developer/visualize/development-visualize-index.asciidoc similarity index 100% rename from docs/development/visualize/development-visualize-index.asciidoc rename to docs/developer/visualize/development-visualize-index.asciidoc diff --git a/docs/development.asciidoc b/docs/development.asciidoc deleted file mode 100644 index 55c2beff074d5..0000000000000 --- a/docs/development.asciidoc +++ /dev/null @@ -1,25 +0,0 @@ -[[development]] -= Contributing to Kibana - -[partintro] --- -Contributing to Kibana can be daunting at first, but it doesn't have to be. If -you're planning a pull request to the Kibana repository, you may want to start -with <>. - -If you'd prefer to use Kibana's internal plugin API, then check out -<>. --- - -include::development/core-development.asciidoc[] - -include::development/plugin-development.asciidoc[] - -include::development/visualize/development-visualize-index.asciidoc[] - -include::development/add-data-guide.asciidoc[] - -include::development/security/index.asciidoc[] - -include::development/pr-review.asciidoc[] - diff --git a/docs/development/core/public/kibana-plugin-public.app.md b/docs/development/core/public/kibana-plugin-public.app.md new file mode 100644 index 0000000000000..60cac357d1fe0 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.app.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) + +## App interface + +Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. + +Signature: + +```typescript +export interface App extends AppBase +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [mount](./kibana-plugin-public.app.mount.md) | (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise<AppUnmount> | A mount function called when the user navigates to this app's route. | + diff --git a/docs/development/core/public/kibana-plugin-public.app.mount.md b/docs/development/core/public/kibana-plugin-public.app.mount.md new file mode 100644 index 0000000000000..dda06b035db4a --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.app.mount.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [App](./kibana-plugin-public.app.md) > [mount](./kibana-plugin-public.app.mount.md) + +## App.mount property + +A mount function called when the user navigates to this app's route. + +Signature: + +```typescript +mount: (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.capabilities.md b/docs/development/core/public/kibana-plugin-public.appbase.capabilities.md new file mode 100644 index 0000000000000..450972e41bb29 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.capabilities.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [capabilities](./kibana-plugin-public.appbase.capabilities.md) + +## AppBase.capabilities property + +Custom capabilities defined by the app. + +Signature: + +```typescript +capabilities?: Partial; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.euiicontype.md b/docs/development/core/public/kibana-plugin-public.appbase.euiicontype.md new file mode 100644 index 0000000000000..99c7e852ff905 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.euiicontype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) + +## AppBase.euiIconType property + +A EUI iconType that will be used for the app's icon. This icon takes precendence over the `icon` property. + +Signature: + +```typescript +euiIconType?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.icon.md b/docs/development/core/public/kibana-plugin-public.appbase.icon.md new file mode 100644 index 0000000000000..d94d0897bc5b7 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.icon.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [icon](./kibana-plugin-public.appbase.icon.md) + +## AppBase.icon property + +A URL to an image file used as an icon. Used as a fallback if `euiIconType` is not provided. + +Signature: + +```typescript +icon?: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.id.md b/docs/development/core/public/kibana-plugin-public.appbase.id.md new file mode 100644 index 0000000000000..57daa0c94bdf6 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [id](./kibana-plugin-public.appbase.id.md) + +## AppBase.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.md b/docs/development/core/public/kibana-plugin-public.appbase.md new file mode 100644 index 0000000000000..338d30e780aaf --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) + +## AppBase interface + + +Signature: + +```typescript +export interface AppBase +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [capabilities](./kibana-plugin-public.appbase.capabilities.md) | Partial<Capabilities> | Custom capabilities defined by the app. | +| [euiIconType](./kibana-plugin-public.appbase.euiicontype.md) | string | A EUI iconType that will be used for the app's icon. This icon takes precendence over the icon property. | +| [icon](./kibana-plugin-public.appbase.icon.md) | string | A URL to an image file used as an icon. Used as a fallback if euiIconType is not provided. | +| [id](./kibana-plugin-public.appbase.id.md) | string | | +| [order](./kibana-plugin-public.appbase.order.md) | number | An ordinal used to sort nav links relative to one another for display. | +| [title](./kibana-plugin-public.appbase.title.md) | string | The title of the application. | +| [tooltip$](./kibana-plugin-public.appbase.tooltip$.md) | Observable<string> | An observable for a tooltip shown when hovering over app link. | + diff --git a/docs/development/core/public/kibana-plugin-public.appbase.order.md b/docs/development/core/public/kibana-plugin-public.appbase.order.md new file mode 100644 index 0000000000000..dc0ea14a7b860 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.order.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [order](./kibana-plugin-public.appbase.order.md) + +## AppBase.order property + +An ordinal used to sort nav links relative to one another for display. + +Signature: + +```typescript +order?: number; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.title.md b/docs/development/core/public/kibana-plugin-public.appbase.title.md new file mode 100644 index 0000000000000..4d0fb0c18e814 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.title.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [title](./kibana-plugin-public.appbase.title.md) + +## AppBase.title property + +The title of the application. + +Signature: + +```typescript +title: string; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appbase.tooltip$.md b/docs/development/core/public/kibana-plugin-public.appbase.tooltip$.md new file mode 100644 index 0000000000000..1b8ca490825f9 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appbase.tooltip$.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppBase](./kibana-plugin-public.appbase.md) > [tooltip$](./kibana-plugin-public.appbase.tooltip$.md) + +## AppBase.tooltip$ property + +An observable for a tooltip shown when hovering over app link. + +Signature: + +```typescript +tooltip$?: Observable; +``` diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.md index a3ab77e43446c..b53873bc0fb8a 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.md +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.md @@ -15,5 +15,6 @@ export interface ApplicationSetup | Method | Description | | --- | --- | -| [registerApp(app)](./kibana-plugin-public.applicationsetup.registerapp.md) | Register an mountable application to the system. Apps will be mounted based on their rootRoute. | +| [register(app)](./kibana-plugin-public.applicationsetup.register.md) | Register an mountable application to the system. | +| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationsetup.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. | diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md new file mode 100644 index 0000000000000..b4ccb6a01c600 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [register](./kibana-plugin-public.applicationsetup.register.md) + +## ApplicationSetup.register() method + +Register an mountable application to the system. + +Signature: + +```typescript +register(app: App): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| app | App | an [App](./kibana-plugin-public.app.md) | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.registerapp.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.registerapp.md deleted file mode 100644 index f2532ae71ca2f..0000000000000 --- a/docs/development/core/public/kibana-plugin-public.applicationsetup.registerapp.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [registerApp](./kibana-plugin-public.applicationsetup.registerapp.md) - -## ApplicationSetup.registerApp() method - -Register an mountable application to the system. Apps will be mounted based on their `rootRoute`. - -Signature: - -```typescript -registerApp(app: App): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| app | App | | - -Returns: - -`void` - diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md new file mode 100644 index 0000000000000..0b5bd8eeb36ec --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) > [registerMountContext](./kibana-plugin-public.applicationsetup.registermountcontext.md) + +## ApplicationSetup.registerMountContext() method + +Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. + +Signature: + +```typescript +registerMountContext(contextName: T, provider: IContextProvider): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | +| provider | IContextProvider<AppMountContext, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.availableapps.md b/docs/development/core/public/kibana-plugin-public.applicationstart.availableapps.md deleted file mode 100644 index 8bbd1dfcd31fa..0000000000000 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.availableapps.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [availableApps](./kibana-plugin-public.applicationstart.availableapps.md) - -## ApplicationStart.availableApps property - -Apps available based on the current capabilities. Should be used to show navigation links and make routing decisions. - -Signature: - -```typescript -availableApps: readonly App[]; -``` diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.geturlforapp.md b/docs/development/core/public/kibana-plugin-public.applicationstart.geturlforapp.md new file mode 100644 index 0000000000000..422fbdf7418c2 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.geturlforapp.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [getUrlForApp](./kibana-plugin-public.applicationstart.geturlforapp.md) + +## ApplicationStart.getUrlForApp() method + +Returns a relative URL to a given app, including the global base path. + +Signature: + +```typescript +getUrlForApp(appId: string, options?: { + path?: string; + }): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appId | string | | +| options | {
path?: string;
} | | + +Returns: + +`string` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.md b/docs/development/core/public/kibana-plugin-public.applicationstart.md index 5854a7c65714e..2a60ff449e44e 100644 --- a/docs/development/core/public/kibana-plugin-public.applicationstart.md +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.md @@ -15,6 +15,13 @@ export interface ApplicationStart | Property | Type | Description | | --- | --- | --- | -| [availableApps](./kibana-plugin-public.applicationstart.availableapps.md) | readonly App[] | Apps available based on the current capabilities. Should be used to show navigation links and make routing decisions. | | [capabilities](./kibana-plugin-public.applicationstart.capabilities.md) | RecursiveReadonly<Capabilities> | Gets the read-only capabilities. | +## Methods + +| Method | Description | +| --- | --- | +| [getUrlForApp(appId, options)](./kibana-plugin-public.applicationstart.geturlforapp.md) | Returns a relative URL to a given app, including the global base path. | +| [navigateToApp(appId, options)](./kibana-plugin-public.applicationstart.navigatetoapp.md) | Navigiate to a given app | +| [registerMountContext(contextName, provider)](./kibana-plugin-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. | + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md b/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md new file mode 100644 index 0000000000000..eef31fe661f54 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.navigatetoapp.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [navigateToApp](./kibana-plugin-public.applicationstart.navigatetoapp.md) + +## ApplicationStart.navigateToApp() method + +Navigiate to a given app + +Signature: + +```typescript +navigateToApp(appId: string, options?: { + path?: string; + state?: any; + }): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appId | string | | +| options | {
path?: string;
state?: any;
} | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md new file mode 100644 index 0000000000000..fc86aaf658b68 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ApplicationStart](./kibana-plugin-public.applicationstart.md) > [registerMountContext](./kibana-plugin-public.applicationstart.registermountcontext.md) + +## ApplicationStart.registerMountContext() method + +Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. + +Signature: + +```typescript +registerMountContext(contextName: T, provider: IContextProvider): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| contextName | T | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. | +| provider | IContextProvider<AppMountContext, T> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.appmountcontext.core.md b/docs/development/core/public/kibana-plugin-public.appmountcontext.core.md new file mode 100644 index 0000000000000..63b3ead814f00 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appmountcontext.core.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountContext](./kibana-plugin-public.appmountcontext.md) > [core](./kibana-plugin-public.appmountcontext.core.md) + +## AppMountContext.core property + +Core service APIs available to mounted applications. + +Signature: + +```typescript +core: { + application: Pick; + chrome: ChromeStart; + docLinks: DocLinksStart; + http: HttpStart; + i18n: I18nStart; + notifications: NotificationsStart; + overlays: OverlayStart; + uiSettings: UiSettingsClientContract; + }; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appmountcontext.md b/docs/development/core/public/kibana-plugin-public.appmountcontext.md new file mode 100644 index 0000000000000..c6541e3eca392 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appmountcontext.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountContext](./kibana-plugin-public.appmountcontext.md) + +## AppMountContext interface + +The context object received when applications are mounted to the DOM. + +Signature: + +```typescript +export interface AppMountContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-public.appmountcontext.core.md) | {
application: Pick<ApplicationStart, 'capabilities' | 'navigateToApp'>;
chrome: ChromeStart;
docLinks: DocLinksStart;
http: HttpStart;
i18n: I18nStart;
notifications: NotificationsStart;
overlays: OverlayStart;
uiSettings: UiSettingsClientContract;
} | Core service APIs available to mounted applications. | + diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md new file mode 100644 index 0000000000000..16c8ffe07fc15 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.appbasepath.md @@ -0,0 +1,53 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) + +## AppMountParameters.appBasePath property + +The base path for configuring the application's router. + +Signature: + +```typescript +appBasePath: string; +``` + +## Example + +How to configure react-router with a base path: + +```ts +// inside your plugin's setup function +export class MyPlugin implements Plugin { + setup({ application }) { + application.register({ + id: 'my-app', + async mount(context, params) { + const { renderApp } = await import('./application'); + return renderApp(context, params); + }, + }); +} + +``` + +```ts +// application.tsx +import React from 'react'; +import ReactDOM from 'react-dom'; +import { BrowserRouter, Route } from 'react-router-dom'; + +export renderApp = (context, { appBasePath, element }) => { + ReactDOM.render( + // pass `appBasePath` to `basename` + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +} + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.element.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.element.md new file mode 100644 index 0000000000000..dbe496c01c215 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.element.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) > [element](./kibana-plugin-public.appmountparameters.element.md) + +## AppMountParameters.element property + +The container element to render the application into. + +Signature: + +```typescript +element: HTMLElement; +``` diff --git a/docs/development/core/public/kibana-plugin-public.appmountparameters.md b/docs/development/core/public/kibana-plugin-public.appmountparameters.md new file mode 100644 index 0000000000000..8733f9cd4915d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appmountparameters.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppMountParameters](./kibana-plugin-public.appmountparameters.md) + +## AppMountParameters interface + + +Signature: + +```typescript +export interface AppMountParameters +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [appBasePath](./kibana-plugin-public.appmountparameters.appbasepath.md) | string | The base path for configuring the application's router. | +| [element](./kibana-plugin-public.appmountparameters.element.md) | HTMLElement | The container element to render the application into. | + diff --git a/docs/development/core/public/kibana-plugin-public.appunmount.md b/docs/development/core/public/kibana-plugin-public.appunmount.md new file mode 100644 index 0000000000000..61782d19ca8c5 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.appunmount.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [AppUnmount](./kibana-plugin-public.appunmount.md) + +## AppUnmount type + +A function called when an application should be unmounted from the page. This function should be synchronous. + +Signature: + +```typescript +export declare type AppUnmount = () => void; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md index 9a6e0a7cc8715..330702a45f633 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md +++ b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md @@ -17,5 +17,6 @@ export interface ChromeBreadcrumb | --- | --- | --- | | [data-test-subj](./kibana-plugin-public.chromebreadcrumb.data-test-subj.md) | string | | | [href](./kibana-plugin-public.chromebreadcrumb.href.md) | string | | +| [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md) | MouseEventHandler<HTMLButtonElement> | | | [text](./kibana-plugin-public.chromebreadcrumb.text.md) | string | | diff --git a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md new file mode 100644 index 0000000000000..1e0ae36e893a1 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) > [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md) + +## ChromeBreadcrumb.onClick property + +Signature: + +```typescript +onClick?: MouseEventHandler; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md b/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md index e4e2ad2c7a3a7..1fef9fc1dc359 100644 --- a/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md +++ b/docs/development/core/public/kibana-plugin-public.chromenavlink.order.md @@ -9,5 +9,5 @@ An ordinal used to sort nav links relative to one another for display. Signature: ```typescript -readonly order: number; +readonly order?: number; ``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.application.md b/docs/development/core/public/kibana-plugin-public.coresetup.application.md new file mode 100644 index 0000000000000..4b39b2c76802b --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.coresetup.application.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [application](./kibana-plugin-public.coresetup.application.md) + +## CoreSetup.application property + +[ApplicationSetup](./kibana-plugin-public.applicationsetup.md) + +Signature: + +```typescript +application: ApplicationSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.coresetup.md b/docs/development/core/public/kibana-plugin-public.coresetup.md index a4b5b88df36dc..9b94e2db52831 100644 --- a/docs/development/core/public/kibana-plugin-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-public.coresetup.md @@ -16,6 +16,7 @@ export interface CoreSetup | Property | Type | Description | | --- | --- | --- | +| [application](./kibana-plugin-public.coresetup.application.md) | ApplicationSetup | [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | | [context](./kibana-plugin-public.coresetup.context.md) | ContextSetup | [ContextSetup](./kibana-plugin-public.contextsetup.md) | | [fatalErrors](./kibana-plugin-public.coresetup.fatalerrors.md) | FatalErrorsSetup | [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | | [http](./kibana-plugin-public.coresetup.http.md) | HttpSetup | [HttpSetup](./kibana-plugin-public.httpsetup.md) | diff --git a/docs/development/core/public/kibana-plugin-public.corestart.application.md b/docs/development/core/public/kibana-plugin-public.corestart.application.md index 1dd05ff947aeb..c26701ca80529 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.application.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.application.md @@ -9,5 +9,5 @@ Signature: ```typescript -application: Pick; +application: ApplicationStart; ``` diff --git a/docs/development/core/public/kibana-plugin-public.corestart.md b/docs/development/core/public/kibana-plugin-public.corestart.md index 446e458735214..5c1626958c4df 100644 --- a/docs/development/core/public/kibana-plugin-public.corestart.md +++ b/docs/development/core/public/kibana-plugin-public.corestart.md @@ -16,7 +16,7 @@ export interface CoreStart | Property | Type | Description | | --- | --- | --- | -| [application](./kibana-plugin-public.corestart.application.md) | Pick<ApplicationStart, 'capabilities'> | [ApplicationStart](./kibana-plugin-public.applicationstart.md) | +| [application](./kibana-plugin-public.corestart.application.md) | ApplicationStart | [ApplicationStart](./kibana-plugin-public.applicationstart.md) | | [chrome](./kibana-plugin-public.corestart.chrome.md) | ChromeStart | [ChromeStart](./kibana-plugin-public.chromestart.md) | | [docLinks](./kibana-plugin-public.corestart.doclinks.md) | DocLinksStart | [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | | [http](./kibana-plugin-public.corestart.http.md) | HttpStart | [HttpStart](./kibana-plugin-public.httpstart.md) | diff --git a/docs/development/core/public/kibana-plugin-public.legacycoresetup.injectedmetadata.md b/docs/development/core/public/kibana-plugin-public.legacycoresetup.injectedmetadata.md new file mode 100644 index 0000000000000..f71277e64ff17 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.legacycoresetup.injectedmetadata.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) > [injectedMetadata](./kibana-plugin-public.legacycoresetup.injectedmetadata.md) + +## LegacyCoreSetup.injectedMetadata property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +injectedMetadata: InjectedMetadataSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacycoresetup.md b/docs/development/core/public/kibana-plugin-public.legacycoresetup.md new file mode 100644 index 0000000000000..f704bc65d12a5 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.legacycoresetup.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) + +## LegacyCoreSetup interface + +> Warning: This API is now obsolete. +> +> + +Setup interface exposed to the legacy platform via the `ui/new_platform` module. + +Signature: + +```typescript +export interface LegacyCoreSetup extends CoreSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [injectedMetadata](./kibana-plugin-public.legacycoresetup.injectedmetadata.md) | InjectedMetadataSetup | | + +## Remarks + +Some methods are not supported in the legacy platform and while present to make this type compatibile with [CoreSetup](./kibana-plugin-public.coresetup.md), unsupported methods will throw exceptions when called. + diff --git a/docs/development/core/public/kibana-plugin-public.legacycorestart.injectedmetadata.md b/docs/development/core/public/kibana-plugin-public.legacycorestart.injectedmetadata.md new file mode 100644 index 0000000000000..cd818c3f5adc7 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.legacycorestart.injectedmetadata.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) > [injectedMetadata](./kibana-plugin-public.legacycorestart.injectedmetadata.md) + +## LegacyCoreStart.injectedMetadata property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +injectedMetadata: InjectedMetadataStart; +``` diff --git a/docs/development/core/public/kibana-plugin-public.legacycorestart.md b/docs/development/core/public/kibana-plugin-public.legacycorestart.md new file mode 100644 index 0000000000000..775c3fb1ffe3d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.legacycorestart.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) + +## LegacyCoreStart interface + +> Warning: This API is now obsolete. +> +> + +Start interface exposed to the legacy platform via the `ui/new_platform` module. + +Signature: + +```typescript +export interface LegacyCoreStart extends CoreStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [injectedMetadata](./kibana-plugin-public.legacycorestart.injectedmetadata.md) | InjectedMetadataStart | | + +## Remarks + +Some methods are not supported in the legacy platform and while present to make this type compatibile with [CoreStart](./kibana-plugin-public.corestart.md), unsupported methods will throw exceptions when called. + diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index 5fda9f9159306..ccabdc62c5e7a 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -23,8 +23,12 @@ The plugin integrates with the core system via lifecycle events: `setup` | Interface | Description | | --- | --- | +| [App](./kibana-plugin-public.app.md) | Extension of [common app properties](./kibana-plugin-public.appbase.md) with the mount function. | +| [AppBase](./kibana-plugin-public.appbase.md) | | | [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | | | [ApplicationStart](./kibana-plugin-public.applicationstart.md) | | +| [AppMountContext](./kibana-plugin-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. | +| [AppMountParameters](./kibana-plugin-public.appmountparameters.md) | | | [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | | [ChromeBadge](./kibana-plugin-public.chromebadge.md) | | | [ChromeBrand](./kibana-plugin-public.chromebrand.md) | | @@ -54,6 +58,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | [HttpServiceBase](./kibana-plugin-public.httpservicebase.md) | | | [I18nStart](./kibana-plugin-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. | | [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | +| [LegacyCoreSetup](./kibana-plugin-public.legacycoresetup.md) | Setup interface exposed to the legacy platform via the ui/new_platform module. | +| [LegacyCoreStart](./kibana-plugin-public.legacycorestart.md) | Start interface exposed to the legacy platform via the ui/new_platform module. | | [LegacyNavLink](./kibana-plugin-public.legacynavlink.md) | | | [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) | | | [NotificationsStart](./kibana-plugin-public.notificationsstart.md) | | @@ -80,6 +86,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | Type Alias | Description | | --- | --- | +| [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. | | [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | | | [HttpBody](./kibana-plugin-public.httpbody.md) | | diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.http.md b/docs/development/core/server/kibana-plugin-server.coresetup.http.md index 30f1bb966175a..254f2728abef1 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.http.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.http.md @@ -14,6 +14,7 @@ http: { registerOnPostAuth: HttpServiceSetup['registerOnPostAuth']; basePath: HttpServiceSetup['basePath']; isTlsEnabled: HttpServiceSetup['isTlsEnabled']; + registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; createRouter: () => IRouter; }; ``` diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.md b/docs/development/core/server/kibana-plugin-server.coresetup.md index 0fdb3ad739771..ed487a570f286 100644 --- a/docs/development/core/server/kibana-plugin-server.coresetup.md +++ b/docs/development/core/server/kibana-plugin-server.coresetup.md @@ -18,5 +18,5 @@ export interface CoreSetup | --- | --- | --- | | [context](./kibana-plugin-server.coresetup.context.md) | {
createContextContainer: ContextSetup['createContextContainer'];
} | | | [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | {
adminClient$: Observable<ClusterClient>;
dataClient$: Observable<ClusterClient>;
createClient: (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ClusterClient;
} | | -| [http](./kibana-plugin-server.coresetup.http.md) | {
createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory'];
registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];
registerAuth: HttpServiceSetup['registerAuth'];
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
basePath: HttpServiceSetup['basePath'];
isTlsEnabled: HttpServiceSetup['isTlsEnabled'];
createRouter: () => IRouter;
} | | +| [http](./kibana-plugin-server.coresetup.http.md) | {
createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory'];
registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];
registerAuth: HttpServiceSetup['registerAuth'];
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
basePath: HttpServiceSetup['basePath'];
isTlsEnabled: HttpServiceSetup['isTlsEnabled'];
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(name: T, provider: RequestHandlerContextProvider<RequestHandlerContext>) => RequestHandlerContextContainer<RequestHandlerContext>;
createRouter: () => IRouter;
} | | diff --git a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.body.md b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.body.md new file mode 100644 index 0000000000000..1a2282aae23a4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.body.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [body](./kibana-plugin-server.customhttpresponseoptions.body.md) + +## CustomHttpResponseOptions.body property + +HTTP message to send to the client + +Signature: + +```typescript +body?: T; +``` diff --git a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.headers.md b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.headers.md new file mode 100644 index 0000000000000..93a36bfe59f5e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.headers.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) > [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md) + +## CustomHttpResponseOptions.headers property + +HTTP Headers with additional information about response + +Signature: + +```typescript +headers?: ResponseHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md index cabee8a47e5ca..3e100f709c8c7 100644 --- a/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md +++ b/docs/development/core/server/kibana-plugin-server.customhttpresponseoptions.md @@ -9,12 +9,14 @@ HTTP response parameters for a response with adjustable status code. Signature: ```typescript -export interface CustomHttpResponseOptions extends HttpResponseOptions +export interface CustomHttpResponseOptions ``` ## Properties | Property | Type | Description | | --- | --- | --- | +| [body](./kibana-plugin-server.customhttpresponseoptions.body.md) | T | HTTP message to send to the client | +| [headers](./kibana-plugin-server.customhttpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | | [statusCode](./kibana-plugin-server.customhttpresponseoptions.statuscode.md) | number | | diff --git a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.body.md b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.body.md new file mode 100644 index 0000000000000..acc800ff4879e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.body.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) > [body](./kibana-plugin-server.errorhttpresponseoptions.body.md) + +## ErrorHttpResponseOptions.body property + +HTTP message to send to the client + +Signature: + +```typescript +body?: ResponseError; +``` diff --git a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.headers.md b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.headers.md new file mode 100644 index 0000000000000..4bf78f8325c13 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.headers.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) > [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md) + +## ErrorHttpResponseOptions.headers property + +HTTP Headers with additional information about response + +Signature: + +```typescript +headers?: ResponseHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.md b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.md new file mode 100644 index 0000000000000..9a5c96881f26c --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.errorhttpresponseoptions.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) + +## ErrorHttpResponseOptions interface + +HTTP response parameters + +Signature: + +```typescript +export interface ErrorHttpResponseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-server.errorhttpresponseoptions.body.md) | ResponseError | HTTP message to send to the client | +| [headers](./kibana-plugin-server.errorhttpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | + diff --git a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.body.md b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.body.md new file mode 100644 index 0000000000000..fb663c3c878a7 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.body.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) > [body](./kibana-plugin-server.httpresponseoptions.body.md) + +## HttpResponseOptions.body property + +HTTP message to send to the client + +Signature: + +```typescript +body?: HttpResponsePayload; +``` diff --git a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md index 8f9ccf22c8c6d..aa0e6cc40b861 100644 --- a/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md +++ b/docs/development/core/server/kibana-plugin-server.httpresponseoptions.md @@ -16,5 +16,6 @@ export interface HttpResponseOptions | Property | Type | Description | | --- | --- | --- | +| [body](./kibana-plugin-server.httpresponseoptions.body.md) | HttpResponsePayload | HTTP message to send to the client | | [headers](./kibana-plugin-server.httpresponseoptions.headers.md) | ResponseHeaders | HTTP Headers with additional information about response | diff --git a/docs/development/core/server/kibana-plugin-server.httpserversetup.md b/docs/development/core/server/kibana-plugin-server.httpserversetup.md index 98edda8f15f41..f495de850aff5 100644 --- a/docs/development/core/server/kibana-plugin-server.httpserversetup.md +++ b/docs/development/core/server/kibana-plugin-server.httpserversetup.md @@ -48,12 +48,13 @@ const validate = { - Declare a function to respond to incoming request. The function will receive `request` object containing request details: url, headers, matched route, as well as validated `params`, `query`, `body`. And `response` object instructing HTTP server to create HTTP response with information sent back to the client as the response body, headers, and HTTP status. Unlike, `hapi` route handler in the Legacy platform, any exception raised during the handler call will generate `500 Server error` response and log error details for further investigation. See below for returning custom error responses. ```ts -const handler = async (request: KibanaRequest, response: ResponseFactory) => { +const handler = async (context: RequestHandlerContext, request: KibanaRequest, response: ResponseFactory) => { const data = await findObject(request.params.id); // creates a command to respond with 'not found' error if (!data) return response.notFound(); // creates a command to send found data to the client and set response headers - return response.ok(data, { + return response.ok({ + body: data, headers: { 'content-type': 'application/json' } @@ -80,7 +81,8 @@ router.get({ async (context, request, response) => { const data = await findObject(request.params.id); if (!data) return response.notFound(); - return response.ok(data, { + return response.ok({ + body: data, headers: { 'content-type': 'application/json' } diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md index 675a4ccfd287b..92bf158ad3312 100644 --- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md +++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md @@ -9,6 +9,7 @@ ```typescript export declare type HttpServiceSetup = Omit & { - createRouter: (path: string) => IRouter; + createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter; + registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; }; ``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorizationerror.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorizationerror.md new file mode 100644 index 0000000000000..0629b8e2b9ade --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorizationerror.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [authorizationError](./kibana-plugin-server.ikibanasocket.authorizationerror.md) + +## IKibanaSocket.authorizationError property + +The reason why the peer's certificate has not been verified. This property becomes available only when `authorized` is `false`. + +Signature: + +```typescript +readonly authorizationError?: Error; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorized.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorized.md new file mode 100644 index 0000000000000..abb68f8e8f0e0 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.authorized.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) > [authorized](./kibana-plugin-server.ikibanasocket.authorized.md) + +## IKibanaSocket.authorized property + +Indicates whether or not the peer certificate was signed by one of the specified CAs. When TLS isn't used the value is `undefined`. + +Signature: + +```typescript +readonly authorized?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-server.ikibanasocket.md b/docs/development/core/server/kibana-plugin-server.ikibanasocket.md index 129a3b1d2311a..d100b1eb2bcd9 100644 --- a/docs/development/core/server/kibana-plugin-server.ikibanasocket.md +++ b/docs/development/core/server/kibana-plugin-server.ikibanasocket.md @@ -12,6 +12,13 @@ A tiny abstraction for TCP socket. export interface IKibanaSocket ``` +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [authorizationError](./kibana-plugin-server.ikibanasocket.authorizationerror.md) | Error | The reason why the peer's certificate has not been verified. This property becomes available only when authorized is false. | +| [authorized](./kibana-plugin-server.ikibanasocket.authorized.md) | boolean | Indicates whether or not the peer certificate was signed by one of the specified CAs. When TLS isn't used the value is undefined. | + ## Methods | Method | Description | diff --git a/docs/development/core/server/kibana-plugin-server.internalcorestart.md b/docs/development/core/server/kibana-plugin-server.internalcorestart.md index 3974ae0582891..4943249d284b0 100644 --- a/docs/development/core/server/kibana-plugin-server.internalcorestart.md +++ b/docs/development/core/server/kibana-plugin-server.internalcorestart.md @@ -10,10 +10,3 @@ ```typescript export interface InternalCoreStart ``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [plugins](./kibana-plugin-server.internalcorestart.plugins.md) | PluginsServiceStart | | - diff --git a/docs/development/core/server/kibana-plugin-server.internalcorestart.plugins.md b/docs/development/core/server/kibana-plugin-server.internalcorestart.plugins.md deleted file mode 100644 index 1f6e17325e31d..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.internalcorestart.plugins.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [InternalCoreStart](./kibana-plugin-server.internalcorestart.md) > [plugins](./kibana-plugin-server.internalcorestart.plugins.md) - -## InternalCoreStart.plugins property - -Signature: - -```typescript -plugins: PluginsServiceStart; -``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.core.md b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.core.md new file mode 100644 index 0000000000000..09ebf1170715b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.core.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) > [core](./kibana-plugin-server.legacyservicesetupdeps.core.md) + +## LegacyServiceSetupDeps.core property + +Signature: + +```typescript +core: InternalCoreSetup & { + plugins: PluginsServiceSetup; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.md b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.md new file mode 100644 index 0000000000000..4475318522dfa --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) + +## LegacyServiceSetupDeps interface + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +export interface LegacyServiceSetupDeps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-server.legacyservicesetupdeps.core.md) | InternalCoreSetup & {
plugins: PluginsServiceSetup;
} | | +| [plugins](./kibana-plugin-server.legacyservicesetupdeps.plugins.md) | Record<string, unknown> | | + diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.plugins.md b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.plugins.md new file mode 100644 index 0000000000000..a51aa478caab5 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.legacyservicesetupdeps.plugins.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) > [plugins](./kibana-plugin-server.legacyservicesetupdeps.plugins.md) + +## LegacyServiceSetupDeps.plugins property + +Signature: + +```typescript +plugins: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.core.md b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.core.md new file mode 100644 index 0000000000000..c5cf473aaa01a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.core.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) > [core](./kibana-plugin-server.legacyservicestartdeps.core.md) + +## LegacyServiceStartDeps.core property + +Signature: + +```typescript +core: InternalCoreStart & { + plugins: PluginsServiceStart; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.md b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.md new file mode 100644 index 0000000000000..801138b64e46a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) + +## LegacyServiceStartDeps interface + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +export interface LegacyServiceStartDeps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-server.legacyservicestartdeps.core.md) | InternalCoreStart & {
plugins: PluginsServiceStart;
} | | +| [plugins](./kibana-plugin-server.legacyservicestartdeps.plugins.md) | Record<string, unknown> | | + diff --git a/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.plugins.md b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.plugins.md new file mode 100644 index 0000000000000..a6d774d35e42e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.legacyservicestartdeps.plugins.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) > [plugins](./kibana-plugin-server.legacyservicestartdeps.plugins.md) + +## LegacyServiceStartDeps.plugins property + +Signature: + +```typescript +plugins: Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md index 7b7e9aee42c01..baecb180096de 100644 --- a/docs/development/core/server/kibana-plugin-server.md +++ b/docs/development/core/server/kibana-plugin-server.md @@ -44,6 +44,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | | [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) | | | [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | | +| [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) | HTTP response parameters | | [FakeRequest](./kibana-plugin-server.fakerequest.md) | Fake request object created manually by Kibana plugins. | | [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) | HTTP response parameters | | [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) | Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to hapi server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. | @@ -54,6 +55,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | [IRouter](./kibana-plugin-server.irouter.md) | Registers route handlers for specified resource path and method. | | [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) | Request specific route information exposed to a handler. | | [LegacyRequest](./kibana-plugin-server.legacyrequest.md) | | +| [LegacyServiceSetupDeps](./kibana-plugin-server.legacyservicesetupdeps.md) | | +| [LegacyServiceStartDeps](./kibana-plugin-server.legacyservicestartdeps.md) | | | [Logger](./kibana-plugin-server.logger.md) | Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. | | [LoggerFactory](./kibana-plugin-server.loggerfactory.md) | The single purpose of LoggerFactory interface is to define a way to retrieve a context-based logger instance. | | [LogMeta](./kibana-plugin-server.logmeta.md) | Contextual metadata | @@ -64,7 +67,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PluginManifest](./kibana-plugin-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | | [PluginsServiceSetup](./kibana-plugin-server.pluginsservicesetup.md) | | | [PluginsServiceStart](./kibana-plugin-server.pluginsservicestart.md) | | -| [ResponseErrorMeta](./kibana-plugin-server.responseerrormeta.md) | Additional metadata to enhance error output or provide error details. | +| [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) | Plugin specific context passed to a route handler. | | [RouteConfig](./kibana-plugin-server.routeconfig.md) | Route specific configuration. | | [RouteConfigOptions](./kibana-plugin-server.routeconfigoptions.md) | Additional route options. | | [SavedObject](./kibana-plugin-server.savedobject.md) | | @@ -133,7 +136,13 @@ The plugin integrates with the core system via lifecycle events: `setup` | [RecursiveReadonly](./kibana-plugin-server.recursivereadonly.md) | | | [RedirectResponseOptions](./kibana-plugin-server.redirectresponseoptions.md) | HTTP response parameters for redirection response | | [RequestHandler](./kibana-plugin-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) functions. | +| [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | +| [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) | Context provider for request handler. Extends request context object with provided functionality or data. | +| [RequestHandlerParams](./kibana-plugin-server.requesthandlerparams.md) | Parameters passed to the request handler function. | +| [RequestHandlerReturn](./kibana-plugin-server.requesthandlerreturn.md) | Expected outcome the request handler function. | | [ResponseError](./kibana-plugin-server.responseerror.md) | Error message and optional data send to the client in case of error. | +| [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) | Additional data to provide error details. | +| [ResponseHeaders](./kibana-plugin-server.responseheaders.md) | Http response headers to set. | | [RouteMethod](./kibana-plugin-server.routemethod.md) | The set of common HTTP methods supported by Kibana routing. | | [SavedObjectAttribute](./kibana-plugin-server.savedobjectattribute.md) | | | [SavedObjectsClientContract](./kibana-plugin-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.\#\# SavedObjectsClient errorsSince the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either:1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md)Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the isXYZError() helpers exposed at SavedObjectsErrorHelpers should be used to understand and manage error responses from the SavedObjectsClient.Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for error.body.error.type or doing substring checks on error.body.error.reason, just use the helpers to understand the meaning of the error:\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }// always rethrow the error unless you handle it throw error; \`\`\`\#\#\# 404s from missing indexFrom the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.\#\#\# 503s from missing indexUnlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's action.auto_create_index setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated.See [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | diff --git a/docs/development/core/server/kibana-plugin-server.requesthandler.md b/docs/development/core/server/kibana-plugin-server.requesthandler.md index bde197fd0f094..0b6a127119d8e 100644 --- a/docs/development/core/server/kibana-plugin-server.requesthandler.md +++ b/docs/development/core/server/kibana-plugin-server.requesthandler.md @@ -9,7 +9,7 @@ A function executed when route path matched requested resource path. Request han Signature: ```typescript -export declare type RequestHandler

= (context: {}, request: KibanaRequest, TypeOf, TypeOf>, response: KibanaResponseFactory) => KibanaResponse | Promise>; +export declare type RequestHandler

= (context: RequestHandlerContext, request: KibanaRequest, TypeOf, TypeOf>, response: KibanaResponseFactory) => KibanaResponse | Promise>; ``` ## Example diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md new file mode 100644 index 0000000000000..3274db0cf508d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) > [core](./kibana-plugin-server.requesthandlercontext.core.md) + +## RequestHandlerContext.core property + +Signature: + +```typescript +core: { + elasticsearch: { + dataClient: ScopedClusterClient; + adminClient: ScopedClusterClient; + }; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md new file mode 100644 index 0000000000000..d7498f04733dd --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContext](./kibana-plugin-server.requesthandlercontext.md) + +## RequestHandlerContext interface + +Plugin specific context passed to a route handler. + +Signature: + +```typescript +export interface RequestHandlerContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [core](./kibana-plugin-server.requesthandlercontext.core.md) | {
elasticsearch: {
dataClient: ScopedClusterClient;
adminClient: ScopedClusterClient;
};
} | | + diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md new file mode 100644 index 0000000000000..afdb488597069 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) + +## RequestHandlerContextContainer type + +An object that handles registration of http request context providers. + +Signature: + +```typescript +export declare type RequestHandlerContextContainer = IContextContainer, RequestHandlerParams>; +``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md new file mode 100644 index 0000000000000..0d9cc6b70b80c --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) + +## RequestHandlerContextProvider type + +Context provider for request handler. Extends request context object with provided functionality or data. + +Signature: + +```typescript +export declare type RequestHandlerContextProvider = IContextProvider; +``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md b/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md new file mode 100644 index 0000000000000..7f466845b4d46 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerParams](./kibana-plugin-server.requesthandlerparams.md) + +## RequestHandlerParams type + +Parameters passed to the request handler function. + +Signature: + +```typescript +export declare type RequestHandlerParams = [KibanaRequest, KibanaResponseFactory]; +``` diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md b/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md new file mode 100644 index 0000000000000..6c01e21b6ecbe --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerReturn](./kibana-plugin-server.requesthandlerreturn.md) + +## RequestHandlerReturn type + +Expected outcome the request handler function. + +Signature: + +```typescript +export declare type RequestHandlerReturn = KibanaResponse; +``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerror.md b/docs/development/core/server/kibana-plugin-server.responseerror.md index 6aa4a4e97ff72..11d5e786d66e8 100644 --- a/docs/development/core/server/kibana-plugin-server.responseerror.md +++ b/docs/development/core/server/kibana-plugin-server.responseerror.md @@ -11,6 +11,6 @@ Error message and optional data send to the client in case of error. ```typescript export declare type ResponseError = string | Error | { message: string | Error; - meta?: ResponseErrorMeta; + attributes?: ResponseErrorAttributes; }; ``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerrorattributes.md b/docs/development/core/server/kibana-plugin-server.responseerrorattributes.md new file mode 100644 index 0000000000000..32cc72e9a0d52 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.responseerrorattributes.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) + +## ResponseErrorAttributes type + +Additional data to provide error details. + +Signature: + +```typescript +export declare type ResponseErrorAttributes = Record; +``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerrormeta.data.md b/docs/development/core/server/kibana-plugin-server.responseerrormeta.data.md deleted file mode 100644 index afef0c88432a4..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.responseerrormeta.data.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseErrorMeta](./kibana-plugin-server.responseerrormeta.md) > [data](./kibana-plugin-server.responseerrormeta.data.md) - -## ResponseErrorMeta.data property - -Signature: - -```typescript -data?: Record; -``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerrormeta.doclink.md b/docs/development/core/server/kibana-plugin-server.responseerrormeta.doclink.md deleted file mode 100644 index 472cb3ef48e36..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.responseerrormeta.doclink.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseErrorMeta](./kibana-plugin-server.responseerrormeta.md) > [docLink](./kibana-plugin-server.responseerrormeta.doclink.md) - -## ResponseErrorMeta.docLink property - -Signature: - -```typescript -docLink?: string; -``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerrormeta.errorcode.md b/docs/development/core/server/kibana-plugin-server.responseerrormeta.errorcode.md deleted file mode 100644 index 1f26f072e0b9a..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.responseerrormeta.errorcode.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseErrorMeta](./kibana-plugin-server.responseerrormeta.md) > [errorCode](./kibana-plugin-server.responseerrormeta.errorcode.md) - -## ResponseErrorMeta.errorCode property - -Signature: - -```typescript -errorCode?: string; -``` diff --git a/docs/development/core/server/kibana-plugin-server.responseerrormeta.md b/docs/development/core/server/kibana-plugin-server.responseerrormeta.md deleted file mode 100644 index 9ab351d013dd7..0000000000000 --- a/docs/development/core/server/kibana-plugin-server.responseerrormeta.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseErrorMeta](./kibana-plugin-server.responseerrormeta.md) - -## ResponseErrorMeta interface - -Additional metadata to enhance error output or provide error details. - -Signature: - -```typescript -export interface ResponseErrorMeta -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [data](./kibana-plugin-server.responseerrormeta.data.md) | Record<string, any> | | -| [docLink](./kibana-plugin-server.responseerrormeta.doclink.md) | string | | -| [errorCode](./kibana-plugin-server.responseerrormeta.errorcode.md) | string | | - diff --git a/docs/development/core/server/kibana-plugin-server.responseheaders.md b/docs/development/core/server/kibana-plugin-server.responseheaders.md new file mode 100644 index 0000000000000..c6ba852b9a624 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.responseheaders.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [ResponseHeaders](./kibana-plugin-server.responseheaders.md) + +## ResponseHeaders type + +Http response headers to set. + +Signature: + +```typescript +export declare type ResponseHeaders = { + [header in KnownHeaders]?: string | string[]; +} & { + [header: string]: string | string[]; +}; +``` diff --git a/docs/discover.asciidoc b/docs/discover.asciidoc deleted file mode 100644 index dd93abe550c02..0000000000000 --- a/docs/discover.asciidoc +++ /dev/null @@ -1,27 +0,0 @@ -[[discover]] -= Discover - -[partintro] --- -*Discover* enables you to explore your data with {kib}'s data discovery functions. -You have access to every document in every index that matches the selected index pattern. -You can submit search queries, filter the search results, and view document data. -You can also see the number of documents that match the search query and get field value statistics. -If a time field is configured for the selected index pattern, the distribution of -documents over time is displayed in a histogram at the top of the page. - -[role="screenshot"] -image::images/Discover-Start.png[Discover] --- - -include::discover/set-time-filter.asciidoc[] - -include::discover/search.asciidoc[] - -include::discover/field-filter.asciidoc[] - -include::discover/document-data.asciidoc[] - -include::discover/context.asciidoc[] - -include::discover/viewing-field-stats.asciidoc[] diff --git a/docs/discover/images/saved-query-management-component-all-privileges.png b/docs/discover/images/saved-query-management-component-all-privileges.png new file mode 100644 index 0000000000000..d3746248f6e27 Binary files /dev/null and b/docs/discover/images/saved-query-management-component-all-privileges.png differ diff --git a/docs/discover/images/saved-query-management-component-delete-query-button.png b/docs/discover/images/saved-query-management-component-delete-query-button.png new file mode 100644 index 0000000000000..23af8022069b6 Binary files /dev/null and b/docs/discover/images/saved-query-management-component-delete-query-button.png differ diff --git a/docs/discover/images/saved-query-management-component-save-as-new-query.png b/docs/discover/images/saved-query-management-component-save-as-new-query.png new file mode 100644 index 0000000000000..4ba4d1d660268 Binary files /dev/null and b/docs/discover/images/saved-query-management-component-save-as-new-query.png differ diff --git a/docs/discover/images/saved-query-management-component-save-as-new.png b/docs/discover/images/saved-query-management-component-save-as-new.png new file mode 100644 index 0000000000000..0899df5c608f5 Binary files /dev/null and b/docs/discover/images/saved-query-management-component-save-as-new.png differ diff --git a/docs/discover/images/saved-query-save-form-default-filters.png b/docs/discover/images/saved-query-save-form-default-filters.png new file mode 100644 index 0000000000000..948e474251a37 Binary files /dev/null and b/docs/discover/images/saved-query-save-form-default-filters.png differ diff --git a/docs/discover/search.asciidoc b/docs/discover/search.asciidoc index 9286b3ce31ba5..790cc669927c1 100644 --- a/docs/discover/search.asciidoc +++ b/docs/discover/search.asciidoc @@ -55,10 +55,10 @@ query language you can also submit queries using the {ref}/query-dsl.html[Elasti [[save-open-search]] -=== Saving and Opening Searches -Saving searches enables you to reload them into Discover and use them as the basis -for <>. Saving a search saves both the search query string -and the currently selected index pattern. +=== Saving searches +A saved search persists your current view of Discover for later retrieval and reuse. You can reload a saved search into Discover, add it to a dashboard, and use it as the basis for a <>. + +A saved search includes the query text, filters, and optionally, the time filter. A saved search also includes the selected columns in the document table, the sort order, and the current index pattern. [role="xpack"] [[discover-read-only-access]] @@ -88,6 +88,78 @@ If the saved search is associated with a different index pattern than is current selected, opening the saved search changes the selected index pattern. The query language used for the saved search will also be automatically selected. +[[save-load-delete-query]] +=== Saving queries +A saved query is a portable collection of query text and filters that you can reuse in <>, <>, and <>. Save a query when you want to: + +* Retrieve results from the same query at a later time without having to reenter the query text, add the filters or set the time filter +* View the results of the same query in multiple apps +* Share your query + +Saved queries don't include information specific to Discover, such as the currently selected columns in the document table, the sort order, and the index pattern. If you want to save your current view of Discover for later retrieval and reuse, create a <> instead. + +[role="xpack"] +==== Read only access +If you have insufficient privileges to save queries, the *Save current query* button isn't visible in the saved query management popover. For more information, see <> + +==== Saving a query +To save the current query text, filters, and time filter: + +. Click *#* in the search bar, next to the query text input. +. Click *Save current query* in the popover. ++ +[role="screenshot"] +image::discover/images/saved-query-management-component-all-privileges.png["Example of the saved query management popover with a list of saved queries with write access",width="80%"] ++ +. Enter a name, a description, and then select the filter options that you want to include. By default, filters are automatically included, but the time filter is not. ++ +[role="screenshot"] +image::discover/images/saved-query-save-form-default-filters.png["Example of the saved query management save form with the filters option included and the time filter option excluded",width="80%"] +. Click *Save*. + +==== Loading a query +To load a saved query into Discover, Dashboard, or Visualize: + +. Click *#* in the search bar, next to the query text input. +. Select the query you want to load. You might need to scroll down to find the query you are looking for. + +==== Saving changes to a query +If you load a query and then make changes to the query text, the filters, or the time filter, you can save the changes as a new query or update the existing query. + +To save the changes as a new query: + +. Click *#* in the search bar, next to the query text input. +. Click *Save as new* in the popover. +. Enter a name and a description, and then select the filter options that you want to include. +. Click *Save*. ++ +[role="screenshot"] +image::discover/images/saved-query-management-component-save-as-new-query.png["Example of the saved query management popover when a query is loaded and we have made changes to the query",width="80%"] + +To save the changes to the current query: + +. Click *#* in the search bar. +. Click *Save changes* in the popover. +. Enter a description, and then select the filter options that you want to include. +. Click *Save*. + +==== Clearing a query +To clear a query that is currently loaded in an application: + +. Click *#* in the search bar. +. Click *Clear* in the popover. + +==== Deleting a query +To completely delete a query: + +. Click *#* in the search bar, next to the query text input. +. Hover over the query you want to delete. +. Click the trash can icon. ++ +[role="screenshot"] +image::discover/images/saved-query-management-component-delete-query-button.png["Example of the saved query management popover when a query is hovered over and we are about to delete a query",width="80%"] + +You can import, export, and delete saved queries from <>. [[select-pattern]] === Changing Which Indices You're Searching diff --git a/docs/getting-started.asciidoc b/docs/getting-started.asciidoc deleted file mode 100644 index c1b31a5153d84..0000000000000 --- a/docs/getting-started.asciidoc +++ /dev/null @@ -1,65 +0,0 @@ -[[getting-started]] -= Getting Started - -[partintro] --- - -You’re new to Kibana and want to give it a try. {kib} has sample data sets and -tutorials to help you get started. - -[float] -=== Sample data - -You can use the <> to take {kib} for a test ride without having -to go through the process of loading data yourself. With one click, -you can install a sample data set and start interacting with -{kib} visualizations in seconds. You can access the sample data -from the {kib} home page. - -[float] - -=== Add data tutorials -{kib} has built-in *Add Data* tutorials to help you set up -data flows in the Elastic Stack. These tutorials are available -from the Kibana home page. In *Add Data to Kibana*, find the data type -you’re interested in, and click its button to view a list of available tutorials. - -[float] -=== Hands-on experience - -The following tutorials walk you through searching, analyzing, -and visualizing data. - -* <>. You'll -learn to filter and query data, edit visualizations, and interact with dashboards. - -* <>. You'll manually load a data set and build -your own visualizations and dashboard. - -[float] -=== Before you begin - -Make sure you've <> and established -a <>. - -If you are running our https://cloud.elastic.co[hosted Elasticsearch Service] -on Elastic Cloud, you can access Kibana with a single click. - - --- - -include::getting-started/add-sample-data.asciidoc[] - -include::getting-started/tutorial-sample-data.asciidoc[] - -include::getting-started/tutorial-full-experience.asciidoc[] - -include::getting-started/tutorial-define-index.asciidoc[] - -include::getting-started/tutorial-discovering.asciidoc[] - -include::getting-started/tutorial-visualizing.asciidoc[] - -include::getting-started/tutorial-dashboard.asciidoc[] - diff --git a/docs/gs-index.asciidoc b/docs/gs-index.asciidoc index 86f229047bace..c5446dda67606 100644 --- a/docs/gs-index.asciidoc +++ b/docs/gs-index.asciidoc @@ -1,5 +1,5 @@ [[kibana-guide]] -= Kibana User Guide += Kibana Guide ////////// release-state can be: released | prerelease | unreleased diff --git a/docs/images/actions_icon.png b/docs/images/actions_icon.png new file mode 100644 index 0000000000000..36e918c8cd181 Binary files /dev/null and b/docs/images/actions_icon.png differ diff --git a/docs/images/canvas-add-pages.gif b/docs/images/canvas-add-pages.gif new file mode 100644 index 0000000000000..99d3c3d6229a4 Binary files /dev/null and b/docs/images/canvas-add-pages.gif differ diff --git a/docs/images/canvas-align-elements.gif b/docs/images/canvas-align-elements.gif new file mode 100644 index 0000000000000..10530df4f83b9 Binary files /dev/null and b/docs/images/canvas-align-elements.gif differ diff --git a/docs/images/canvas-click-drag-element.gif b/docs/images/canvas-click-drag-element.gif new file mode 100644 index 0000000000000..34f4268caf6f5 Binary files /dev/null and b/docs/images/canvas-click-drag-element.gif differ diff --git a/docs/images/canvas-distribute-elements.gif b/docs/images/canvas-distribute-elements.gif new file mode 100644 index 0000000000000..d4b6985ac7e52 Binary files /dev/null and b/docs/images/canvas-distribute-elements.gif differ diff --git a/docs/images/canvas-element-order.gif b/docs/images/canvas-element-order.gif new file mode 100644 index 0000000000000..e2911367e7dfa Binary files /dev/null and b/docs/images/canvas-element-order.gif differ diff --git a/docs/images/canvas-element-select.gif b/docs/images/canvas-element-select.gif new file mode 100644 index 0000000000000..db749f5e9397a Binary files /dev/null and b/docs/images/canvas-element-select.gif differ diff --git a/docs/images/canvas-export-workpad.png b/docs/images/canvas-export-workpad.png new file mode 100644 index 0000000000000..687c8a121b65a Binary files /dev/null and b/docs/images/canvas-export-workpad.png differ diff --git a/docs/images/canvas-fullscreen.gif b/docs/images/canvas-fullscreen.gif new file mode 100644 index 0000000000000..5a06f9158ecf6 Binary files /dev/null and b/docs/images/canvas-fullscreen.gif differ diff --git a/docs/images/canvas-fullscreen.png b/docs/images/canvas-fullscreen.png new file mode 100644 index 0000000000000..b26e9493f17b5 Binary files /dev/null and b/docs/images/canvas-fullscreen.png differ diff --git a/docs/images/canvas-move-pixel.gif b/docs/images/canvas-move-pixel.gif new file mode 100644 index 0000000000000..228f0f7b7e18c Binary files /dev/null and b/docs/images/canvas-move-pixel.gif differ diff --git a/docs/images/canvas-refresh-interval.png b/docs/images/canvas-refresh-interval.png new file mode 100644 index 0000000000000..f1c840f503ec4 Binary files /dev/null and b/docs/images/canvas-refresh-interval.png differ diff --git a/docs/images/canvas-resize-element.gif b/docs/images/canvas-resize-element.gif new file mode 100644 index 0000000000000..d2d2ab06bbb42 Binary files /dev/null and b/docs/images/canvas-resize-element.gif differ diff --git a/docs/images/canvas-zoom-controls.png b/docs/images/canvas-zoom-controls.png new file mode 100644 index 0000000000000..e0fc020e262a7 Binary files /dev/null and b/docs/images/canvas-zoom-controls.png differ diff --git a/docs/images/canvas-zoom.gif b/docs/images/canvas-zoom.gif new file mode 100644 index 0000000000000..584118d75a43f Binary files /dev/null and b/docs/images/canvas-zoom.gif differ diff --git a/docs/images/management-saved-objects.png b/docs/images/management-saved-objects.png index 24b01f58c061a..8ae68c8102b05 100644 Binary files a/docs/images/management-saved-objects.png and b/docs/images/management-saved-objects.png differ diff --git a/docs/index.asciidoc b/docs/index.asciidoc index db8e095b6e9af..491a9629e983e 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -1,5 +1,5 @@ [[kibana-guide]] -= Kibana User Guide += Kibana Guide :include-xpack: true :lang: en @@ -7,7 +7,7 @@ :blog-ref: https://www.elastic.co/blog/ :wikipedia: https://en.wikipedia.org/wiki -include::{asciidoc-dir}/../../shared/versions.asciidoc[] +include::{asciidoc-dir}/../../shared/versions/stack/{source_branch}.asciidoc[] :docker-repo: docker.elastic.co/kibana/kibana :docker-image: docker.elastic.co/kibana/kibana:{version} @@ -20,63 +20,7 @@ include::{asciidoc-dir}/../../shared/versions.asciidoc[] include::{asciidoc-dir}/../../shared/attributes.asciidoc[] -include::introduction.asciidoc[] - -include::setup.asciidoc[] - -include::monitoring/configuring-monitoring.asciidoc[] - -include::security/securing-kibana.asciidoc[] - -include::getting-started.asciidoc[] - -include::discover.asciidoc[] - -include::visualize.asciidoc[] - -include::dashboard.asciidoc[] - -include::canvas.asciidoc[] - -include::ml/index.asciidoc[] - -include::maps/index.asciidoc[] - -include::code/index.asciidoc[] - -include::infrastructure/index.asciidoc[] - -include::logs/index.asciidoc[] - -include::apm/index.asciidoc[] - -include::uptime/index.asciidoc[] - -include::siem/index.asciidoc[] - -include::graph/index.asciidoc[] - -include::dev-tools.asciidoc[] - -include::monitoring/index.asciidoc[] - -include::management.asciidoc[] - -include::spaces/index.asciidoc[] - -include::security/index.asciidoc[] - -include::management/watcher-ui/index.asciidoc[] - -include::management/upgrade-assistant/index.asciidoc[] - -include::reporting/index.asciidoc[] - -include::api.asciidoc[] - -include::plugins.asciidoc[] - -include::development.asciidoc[] +include::user/index.asciidoc[] include::limitations.asciidoc[] @@ -86,4 +30,6 @@ include::migration.asciidoc[] include::CHANGELOG.asciidoc[] +include::developer/index.asciidoc[] + include::redirects.asciidoc[] diff --git a/docs/infrastructure/getting-started.asciidoc b/docs/infrastructure/getting-started.asciidoc new file mode 100644 index 0000000000000..510d53ccdccc0 --- /dev/null +++ b/docs/infrastructure/getting-started.asciidoc @@ -0,0 +1,11 @@ +[role="xpack"] +[[xpack-metrics-getting-started]] +== Getting started with infrastructure monitoring + +To get started with the Infrastructure app in Kibana, you need to start collecting metrics data for your infrastructure. + +Kibana provides step-by-step instructions to help you add metrics data. +The {infra-guide}[Infrastructure Monitoring Guide] is a good source for more detailed information and instructions. + +[role="screenshot"] +image::infrastructure/images/metrics-add-data.png[Screenshot showing Add metric data to Kibana UI] diff --git a/docs/infrastructure/images/infra-sysmon.jpg b/docs/infrastructure/images/infra-sysmon.jpg deleted file mode 100644 index 36afcb82061cc..0000000000000 Binary files a/docs/infrastructure/images/infra-sysmon.jpg and /dev/null differ diff --git a/docs/infrastructure/images/infra-sysmon.png b/docs/infrastructure/images/infra-sysmon.png new file mode 100644 index 0000000000000..5b82d8c9b4e19 Binary files /dev/null and b/docs/infrastructure/images/infra-sysmon.png differ diff --git a/docs/infrastructure/images/infra-time-selector.png b/docs/infrastructure/images/infra-time-selector.png new file mode 100644 index 0000000000000..181fac4c7b39b Binary files /dev/null and b/docs/infrastructure/images/infra-time-selector.png differ diff --git a/docs/infrastructure/images/infra-view-metrics.png b/docs/infrastructure/images/infra-view-metrics.png new file mode 100644 index 0000000000000..9ad862ec6515d Binary files /dev/null and b/docs/infrastructure/images/infra-view-metrics.png differ diff --git a/docs/infrastructure/images/infrastructure-configure-source-dialog.png b/docs/infrastructure/images/infrastructure-configure-source-dialog.png deleted file mode 100644 index 31f496aaf56c7..0000000000000 Binary files a/docs/infrastructure/images/infrastructure-configure-source-dialog.png and /dev/null differ diff --git a/docs/infrastructure/images/infrastructure-configure-source-gear-icon.png b/docs/infrastructure/images/infrastructure-configure-source-gear-icon.png deleted file mode 100644 index 8b062c627143a..0000000000000 Binary files a/docs/infrastructure/images/infrastructure-configure-source-gear-icon.png and /dev/null differ diff --git a/docs/infrastructure/images/infrastructure-configure-source.png b/docs/infrastructure/images/infrastructure-configure-source.png deleted file mode 100644 index d1e9a2fd59246..0000000000000 Binary files a/docs/infrastructure/images/infrastructure-configure-source.png and /dev/null differ diff --git a/docs/infrastructure/images/metrics-add-data.png b/docs/infrastructure/images/metrics-add-data.png new file mode 100644 index 0000000000000..d9640e0d9f5da Binary files /dev/null and b/docs/infrastructure/images/metrics-add-data.png differ diff --git a/docs/infrastructure/images/read-only-badge.png b/docs/infrastructure/images/read-only-badge.png deleted file mode 100644 index 7911a21e4985f..0000000000000 Binary files a/docs/infrastructure/images/read-only-badge.png and /dev/null differ diff --git a/docs/infrastructure/images/time-filter-calendar.png b/docs/infrastructure/images/time-filter-calendar.png new file mode 100644 index 0000000000000..d0019c99fe893 Binary files /dev/null and b/docs/infrastructure/images/time-filter-calendar.png differ diff --git a/docs/infrastructure/images/time-filter-clock.png b/docs/infrastructure/images/time-filter-clock.png new file mode 100644 index 0000000000000..fe8542aad41de Binary files /dev/null and b/docs/infrastructure/images/time-filter-clock.png differ diff --git a/docs/infrastructure/index.asciidoc b/docs/infrastructure/index.asciidoc index c48d78d6cf386..33389345fff77 100644 --- a/docs/infrastructure/index.asciidoc +++ b/docs/infrastructure/index.asciidoc @@ -4,83 +4,31 @@ [partintro] -- -Use the interactive Infrastructure UI to monitor your infrastructure and -identify problems in real time. You can explore metrics and logs for common -servers, containers, and services. +The Infrastructure app enables you to monitor your infrastructure and identify problems in real time. +You start with a visual summary of your infrastructure where you can view basic metrics for common servers, containers, and services. +Then you can drill down to view more detailed metrics or other information for that component. -[role="screenshot"] -image::infrastructure/images/infra-sysmon.jpg[Infrastructure Overview in Kibana] - - -[float] -== Add data - -Kibana provides step-by-step instructions to help you add log data. The -{infra-guide}[Infrastructure Monitoring Guide] is a good source for more -detailed information and instructions. +You can: -[float] -== Configure data sources +* View an inventory of your infrastructure by hosts, Kubernetes pod or Docker containers. +You can group and filter the data in various ways to help you identify the items that interest you. -The `metricbeat-*` index pattern is used to query the data by default. -If your metrics are located in a different set of indices, or use a -different timestamp field, you can adjust the source configuration via the user -interface or the {kib} configuration file. +* View current and historic values for metrics such as CPU usage, memory usage, and network traffic for each component. +The available metrics depend on the kind of component being inspected. -NOTE: Logs and Infrastructure share a common data source definition in -each space. Changes in one of them can influence the data displayed in the -other. - -[float] -=== Configure source - -Configure source can be accessed via the corresponding -image:logs/images/logs-configure-source-gear-icon.png[Configure source icon] -button in the toolbar: - -[role="screenshot"] -image::infrastructure/images/infrastructure-configure-source.png[Configure Infrastructure UI source button in Kibana] +* Use *Metrics Explorer* to group and visualize multiple customizable metrics for one or more components in a graphical format. +You can optionally save these views and add them to {kibana-ref}/dashboard.html[dashboards]. -This opens the source configuration fly-out dialog, in which the following -configuration items can be inspected and adjusted: +* Seamlessly switch to view the corresponding logs, application traces or uptime information for a component. -* *Name*: The name of the source configuration. -* *Indices*: The patterns of the elasticsearch indices to read metrics and logs - from. -* *Fields*: The names of particular fields in the indices that need to be known - to the Infrastructure and Logs UIs in order to query and interpret the data - correctly. +To get started, you need to <>. Then you can <>. [role="screenshot"] -image::infrastructure/images/infrastructure-configure-source-dialog.png[Configure Infrastructure UI source dialog in Kibana] - -TIP: If <> are enabled in your Kibana instance, any configuration -changes performed via Configure source are specific to that space. You can -therefore easily make different subsets of the data available by creating -multiple spaces with different data source configurations. - -[float] -[[infra-read-only-access]] -=== Read only access -When you have insufficient privileges to change the source configuration, the following -indicator in Kibana will be displayed. The buttons to change the source configuration -won't be visible. For more information on granting access to -Kibana see <>. - -[role="screenshot"] -image::infrastructure/images/read-only-badge.png[Example of Infrastructure's read only access indicator in Kibana's header] - - -[float] -=== Configuration file - -The settings in the configuration file are used as a fallback when no other -configuration for that space has been defined. They are located in the -configuration namespace `xpack.infra.sources.default`. See -<> for a complete list of the possible entries. +image::infrastructure/images/infra-sysmon.png[Infrastructure Overview in Kibana] -- -include::monitor.asciidoc[] +include::getting-started.asciidoc[] include::infra-ui.asciidoc[] +include::view-metrics.asciidoc[] include::metrics-explorer.asciidoc[] diff --git a/docs/infrastructure/infra-ui.asciidoc b/docs/infrastructure/infra-ui.asciidoc index a736d88971aba..be8fc29b98ab2 100644 --- a/docs/infrastructure/infra-ui.asciidoc +++ b/docs/infrastructure/infra-ui.asciidoc @@ -1,68 +1,112 @@ [role="xpack"] [[infra-ui]] -== Using the Infrastructure UI +== Using the Infrastructure app -Use the Infrastructure UI in {kib} to monitor your infrastructure and identify -problems in real time. +Use the Infrastructure app in {kib} to monitor your infrastructure and identify problems in real time. +You can explore metrics for hosts, containers, and services. +You can also drill down to view more detailed metrics, or seamlessly switch to view the corresponding logs, application traces, and uptime information. -You start with an overview of your infrastructure. -Then you can use the interactive UI to drill down into areas of interest. +Initially, the *Inventory* tab shows an overview of the hosts in of your infrastructure and the current CPU usage for each host. +From here, you can drill down into areas of interest. [role="screenshot"] -image::infrastructure/images/infra-sysmon.jpg[Infrastructure Overview in Kibana] - -TIP: Right-click an element to jump to related logs or metrics. +image::infrastructure/images/infra-sysmon.png[Infrastructure Overview in Kibana] [float] [[infra-cat]] -=== View your infrastructure by hosts or container - -Select the high-level view: *Hosts*, *Kubernetes*, or *Docker*. -When you change views, you can see the same data through the perspective of a -different category. +=== Choose the high-level view of your infrastructure -[float] -[[infra-search]] -=== Use the power of Search +Select the high-level view from *Hosts*, *Kubernetes*, or *Docker*. +When you change views, you see the same data through the perspective of a different category. -The Search bar is always available. You can use it to perform adhoc or structured searches. -The Search feature can surface the information you're looking for, even if the -other options you have selected would normally filter it out. +The default representation is the *Map view*, which shows your components in a _waffle map_ of one or more rectangular grids. +If the view you select has a large number of components, you can hover over a component to see the details for that component. Alternatively, if you would prefer to see your infrastructure as a table, click *Table view*. [float] [[infra-metric]] -=== Start at a high-level by selecting the metric +=== Select the metric to view -This filter helps you start focusing on potential problem areas that may need -further investigation. You'll see metrics that are most relevant for hosts or -the container you selected. +Select the metric to view from the *Metric* dropdown list. +The available metrics are those that are most relevant for the high-level view you selected. [float] [[infra-group]] -=== Group components +=== Group components + +Select the way you want to group the infrastructure components from the *Group By* dropdown list. +The available options are specific to your physical, virtual, or container-based infrastructure. +Examples of grouping options include *Availability Zone*, *Machine Type*, *Project ID*, and *Cloud Provider* for hosts, and *Namespace* and *Node* for Kubernetes. + +[float] +[[infra-search]] +=== Use the power of search -The *Group By* selector offers grouping options that are native and specific for -your physical, virtual, and container-based infrastructure. -Examples include Availability Zone, Machine Type, Project ID, and Cloud Provider -for Hosts, and Namespace and Node for Kubernetes. +Use the search bar to perform ad hoc searches for specific text. +You can also create structured searches using {kibana-ref}/kuery-query.html[Kibana Query Language]. +For example, enter `host.hostname : "host1"` to see only the information for `host1`. [float] [[infra-date]] -=== Specify the date range +=== Specify the time and date -Use the time selector to focus on a specific timeframe. +Click the time selector image:infrastructure/images/infra-time-selector.png[time selector icon] to choose the timeframe for the metrics. +The values shown are the values for the last minute at the specified time and date. [float] [[infra-refresh]] -=== Auto-refresh or pause +=== Auto-refresh metrics -Set auto-refresh to keep up-to-date information coming in, or stop -refreshing to focus on historical data without new distractions. +Select *Auto-refresh* to keep up-to-date metrics information coming in, or *Stop refreshing* to focus on historical data without new distractions. [float] [[infra-configure-source]] -=== Adapt to your metric source +=== Configure the data to use for your metrics + +The default source configuration for metrics is specified in the {kibana-ref}/infrastructure-ui-settings-kb.html[Infrastructure app settings] in the {kibana-ref}/settings.html[Kibana configuration file]. +The default configuration uses the `metricbeat-*` index pattern to query the data. +The default configuration also defines field settings for things like timestamps and container names. + +If your metrics have custom index patterns, or use non-default field settings, you can override the default settings. +Click *Configuration* to change the settings. +This opens the *Configure source* fly-out dialog. + +NOTE: These settings are shared with logs. Changes you make here may also affect the settings used by the *Logs* app. + +In the *Configure source* dialog, you can change the following values: + +* *Name*: the name of the source configuration +* *Indices*: the index pattern or patterns in the Elasticsearch indices to read metrics data and log data + from +* *Fields*: the names of specific fields in the indices that are used to query and interpret the data correctly + +TIP: If <> are enabled in your Kibana instance, any configuration changes you make here are specific to the current space. +You can make different subsets of data available by creating multiple spaces with different data source configurations. + +TIP: If you don't see the *Configuration* option, you may not have sufficient privileges to change the source configuration. +For more information see <>. + +[float] +[[infra-metrics-explorer]] +=== Visualize multiple metrics in Metrics Explorer + +<> allows you to visualize and analyze metrics for multiple components in a powerful and configurable way. Click the *Metrics Explorer* tab to get started. + +[float] +[[infra-drill-down]] +=== Drill down for related information + +Hover over a component to see more information about that component. + +Click a component to see the other actions available for that component. +You can: + +* Select *View Metrics* to <>. + +* Select *View Logs* to <> in the *Logs* app. + +Depending on the features you have installed and configured, you may also be able to: + +* Select *View APM* to <> in the *APM* app. + +* Select *View Uptime* to <> in the *Uptime* app. -Using a custom index pattern to store the metrics, or want to limit the entries -presented in a space? Use configure source to change the index pattern and -other settings. diff --git a/docs/infrastructure/metrics-explorer.asciidoc b/docs/infrastructure/metrics-explorer.asciidoc index 008f7ee1bacc6..729d5ff97efd7 100644 --- a/docs/infrastructure/metrics-explorer.asciidoc +++ b/docs/infrastructure/metrics-explorer.asciidoc @@ -1,10 +1,10 @@ [role="xpack"] [[metrics-explorer]] - == Metrics Explorer -Metrics Explorer allows you to visualize metrics data collected by Metricbeat and group it in various ways to visualize multiple metrics. -It can be a starting point for further investigations. +Metrics Explorer in the Infrastructure app in Kibana allows you to group and visualise multiple customisable metrics for one or more components in a graphical format. +This can be a starting point for further investigations. +You can also save your views and add them to {kibana-ref}/dashboard.html[dashboards]. [role="screenshot"] image::infrastructure/images/metrics-explorer-screen.png[Metrics Explorer in Kibana] @@ -13,13 +13,13 @@ image::infrastructure/images/metrics-explorer-screen.png[Metrics Explorer in Kib [[metrics-explorer-requirements]] === Metrics Explorer requirements and considerations -* The Metrics Explorer uses data collected from {metricbeat-ref}/metricbeat-overview.html[Metricbeat]. -* You need read permissions on `metricbeat-*` or the metric index specified in the Infrastructure configuration UI. -* Metrics Explorer uses the timestamp field set in the Infrastructure configuration UI. +* Metrics Explorer uses data collected from {metricbeat-ref}/metricbeat-overview.html[Metricbeat]. +* You need read permissions on `metricbeat-*` or the metric index specified in the Infrastructure configuration. +* Metrics Explorer uses the timestamp field set in the Infrastructure configuration. By default that is set to `@timestamp`. * The interval for the X Axis is set to `auto`. The bucket size is determined by the time range. -* *Open in Visualize* requires you to have access to the Visualize app, otherwise it is not available. +* To use *Open in Visualize* you need access to the Visualize app. [float] [[metrics-explorer-tutorial]] @@ -49,7 +49,7 @@ If you only have metrics for a single host, you will see a single graph. Congratulations! Either way, you've explored your first metric. 5. Let's explore a bit further. -In the upper right hand corner of the graph for one of the hosts, select the *Actions* dropdown and click *Add Filter* to show ony the metrics for that host. +In the upper right hand corner of the graph for one of the hosts, select the *Actions* dropdown and click *Add Filter* to show only the metrics for that host. This adds a {kibana-ref}/kuery-query.html[Kibana Query Language] filter for `host.name` in the second row of the Metrics Explorer configuration. If you only have one host, the graph will not change as you are already exploring metrics for a single host. diff --git a/docs/infrastructure/monitor.asciidoc b/docs/infrastructure/monitor.asciidoc deleted file mode 100644 index 90b27460e89e4..0000000000000 --- a/docs/infrastructure/monitor.asciidoc +++ /dev/null @@ -1,35 +0,0 @@ -[role="xpack"] -[[monitor-infra]] -== Monitor your infrastructure - -You start with a visual summary of your infrastructure. -Then you can drill down into areas of interest. - -[float] -=== Monitor hosts and containers - -View your infrastructure by hosts or containers. The UI helps you group, filter, -and target data to help you find what you seek. - -[float] -=== View metrics - -View relevant metric information such as CPU usage, memory usage, load, and inbound or -outbound traffic. - -[float] -=== View logs - -View real-time and historical logs in the same viewer, streaming or pausing as needed. -When you stream logs, the most recent event appears at the bottom of console. -You can easily correlate metrics and logs. Right-click an element in the -Infrastructure UI, and select *View logs*. - - - - - - - - - diff --git a/docs/infrastructure/view-metrics.asciidoc b/docs/infrastructure/view-metrics.asciidoc new file mode 100644 index 0000000000000..229d91ae5aae4 --- /dev/null +++ b/docs/infrastructure/view-metrics.asciidoc @@ -0,0 +1,40 @@ +[role="xpack"] +[[xpack-view-metrics]] + +== Viewing infrastructure metrics + +When you select *View Metrics* for a component in your infrastructure from the <>, you can view detailed metrics for that component, and for any related components. +You can also view additional component metadata. + +[role="screenshot"] +image::infrastructure/images/infra-view-metrics.png[Infrastructure View Metrics in Kibana] + +[float] +[[infra-view-metrics-date]] +=== Specify the time and date range + +Use the time filter to select the time and date range for the metrics. + +To quickly select some popular time range options, click the calendar dropdown image:infrastructure/images/time-filter-calendar.png[]. In this popup you can choose from: + +* *Quick select* to choose a recent time range, and use the back and forward arrows to move through the time ranges +* *Commonly used* to choose a time range from some commonly used options such as *Last 15 minutes*, *Today*, or *Week to date* +* *Refresh every* to specify an auto-refresh rate + +NOTE: When you start auto-refresh from within this dialog, the calendar dropdown changes to a clock image:infrastructure/images/time-filter-clock.png[]. + +For complete control over the start and end times, click the start time or end time shown in the bar beside the calendar dropdown. In this popup, you can choose from the *Absolute*, *Relative* or *Now* tabs, then specify the required options. + +[float] +[[infra-view-refresh-metrics-date]] +=== Refresh the metrics + +You can click *Refresh* to manually refresh the metrics. + +[float] +[[infra-view-go-to-chart]] +=== Go to a specific chart + +The charts available for this component are shown in a list on the left of the page. Click a chart in the list to quickly go to that chart. + + diff --git a/docs/logs/configuring.asciidoc b/docs/logs/configuring.asciidoc index 4c164c1a7ddcc..f2aa1e5e17b8f 100644 --- a/docs/logs/configuring.asciidoc +++ b/docs/logs/configuring.asciidoc @@ -3,95 +3,48 @@ :ecs-link: {ecs-ref}[Elastic Common Schema (ECS)] -== Configuring the Logs UI +== Configuring the Logs data -The `filebeat-*` index pattern is used to query data by default. If your logs -are located in a different set of indices, use a different timestamp field, or -contain parsed fields which you want to expose as individual columns, you can -adjust the source configuration via the user interface or the {kib} -configuration file. +The default source configuration for logs is specified in the {kibana-ref}/logs-ui-settings-kb.html[Logs app settings] in the {kibana-ref}/settings.html[Kibana configuration file]. +The default configuration uses the `filebeat-*` index pattern to query the data. +The default configuration also defines field settings for things like timestamps and container names, and the default columns to show in the logs pane. -NOTE: Logs and Infrastructure share a common data source definition in -each space. Changes in one of them can influence the data displayed in the -other. +If your logs have custom index patterns, or use non-default field settings, or contain parsed fields which you want to expose as individual columns, you can override the default settings. +Click *Configuration* to change the settings. +This opens the *Configure source* fly-out dialog. -[float] -=== Configure source - -*Configure source* can be accessed via -image:logs/images/logs-configure-source-gear-icon.png[Configure source icon] -in the toolbar. - -[role="screenshot"] -image::logs/images/logs-configure-source.png[Configure Logs UI source button in Kibana] +NOTE: These settings are shared with metrics. Changes you make here may also affect the settings used by the *Metrics* app. -This opens the source configuration fly-out dialog with multiple tabs, where -you can inspect and adjust various index settings and log column configuration. - -TIP: If <> are enabled in your Kibana instance, any configuration -changes performed via *Configure source* are specific to that space. You can -therefore easily make different subsets of the data available by creating -multiple spaces with different data source configurations. - -[float] -[[logs-read-only-access]] -==== Read only access -When you have insufficient privileges to change the source configuration, the -following indicator in Kibana will be displayed, and the buttons to change the -source configuration won't be visible. For more information, see -<>. +TIP: If <> are enabled in your Kibana instance, any configuration changes you make here are specific to the current space. +You can make different subsets of data available by creating multiple spaces with different data source configurations. -[role="screenshot"] -image::logs/images/read-only-badge.png[Example of Logs' read only access indicator in Kibana's header] +TIP: If you don't see the *Configuration* option, you may not have sufficient privileges to change the source configuration. +For more information see <>. [float] -==== Indices and fields configuration +=== Indices and fields tab -The *Indices and fields* tab provides access to the following configuration -items: +In the *Indices and fields* tab, you can change the following values: -* *Name*: The name of the source configuration. -* *Indices*: The patterns of the Elasticsearch indices to read metrics and logs - from. -* *Fields*: The names of particular fields in the indices that need to be known - to the Infrastructure and Logs UIs in order to query and interpret the data - correctly. - -[role="screenshot"] -image::logs/images/logs-configure-source-dialog-indices-tab.png[Configure logs UI source indices and fields dialog in Kibana] +* *Name*: the name of the source configuration +* *Indices*: the index pattern or patterns in the Elasticsearch indices to read metrics data and log data from +* *Fields*: the names of specific fields in the indices that are used to query and interpret the data correctly [float] ==== Log columns configuration -The *Log columns* tab enables you to change the set of columns that are -displayed in the Logs UI. By default the following columns are shown: - -* *Timestamp*: The log entry's timestamp as defined in the `timestamp` field. -* *events.dataset*: The event dataset as indicated by this {ecs-link} field. -* *Message*: The message extracted from the document. The exact content of that - field depends on the type of log message. If no special type is detected, the - {ecs-link} field `message` is used. - -[role="screenshot"] -image::logs/images/logs-configure-source-dialog-log-columns-tab.png[Configure logs UI source columns dialog in Kibana] +In the *Log columns* tab you can change the columns that are displayed in the Logs app. +By default the following columns are shown: -To add a new column, click -image:logs/images/logs-configure-source-dialog-add-column-button.png[Add column] -above the list. This will cause a popover to be shown in which you can filter a -list of the available fields and select one for inclusion: +* *Timestamp*: The timestamp of the log entry from the `timestamp` field. +* *Message*: The message extracted from the document. +The content of this field depends on the type of log message. +If no special log message type is detected, the {ecs-link} field `message` is used. +// ++ add a better link. The actual page location is ecs-base -[role="screenshot"] -image::logs/images/logs-configure-source-dialog-add-column-popover.png[Configure logs UI source add columns popover in Kibana] - -To remove a column, click -image:logs/images/logs-configure-source-dialog-remove-column-button.png[Remove column] -in the respective entry. The list must contain at least one column to apply the -changes. - -[float] -=== Configuration file +To add a new column, click *Add column*. +In the list of available fields, select the field you want to add. +You can start typing a field name in the search box to filter the field list by that name. -The settings in the configuration file are used as a fallback when no other -configuration for that space has been defined. They are located in the -configuration namespace `xpack.infra.sources.default`. See -<> for a complete list of the possible entries. +To remove an existing column, click the *Remove this column* icon +image:logs/images/logs-configure-source-dialog-remove-column-button.png[Remove column]. \ No newline at end of file diff --git a/docs/logs/getting-started.asciidoc b/docs/logs/getting-started.asciidoc index cb9f180b02ba3..1ed8798a4b87f 100644 --- a/docs/logs/getting-started.asciidoc +++ b/docs/logs/getting-started.asciidoc @@ -1,10 +1,11 @@ [role="xpack"] [[xpack-logs-getting-started]] -== Getting started with the Logs UI +== Getting started with logs monitoring -Kibana provides step-by-step instructions to help you add log data. The -{infra-guide}[Infrastructure Monitoring Guide] is a good source for more -detailed information and instructions. +To get started with the Logs app in Kibana, you need to start collecting logs data for your infrastructure. + +Kibana provides step-by-step instructions to help you add logs data. +The {infra-guide}[Infrastructure Monitoring Guide] is a good source for more detailed information and instructions. [role="screenshot"] -image::logs/images/logs-add-data.png[Included data ingestion tutorials in Kibana] +image::logs/images/logs-add-data.png[Screenshot showing Add logging data in Kibana] diff --git a/docs/logs/images/log-details-actions.png b/docs/logs/images/log-details-actions.png deleted file mode 100644 index 49192d0e3135c..0000000000000 Binary files a/docs/logs/images/log-details-actions.png and /dev/null differ diff --git a/docs/logs/images/log-details-filter.png b/docs/logs/images/log-details-filter.png deleted file mode 100644 index 5037c848d83fe..0000000000000 Binary files a/docs/logs/images/log-details-filter.png and /dev/null differ diff --git a/docs/logs/images/log-details-flyover.png b/docs/logs/images/log-details-flyover.png deleted file mode 100644 index b28040d0e1425..0000000000000 Binary files a/docs/logs/images/log-details-flyover.png and /dev/null differ diff --git a/docs/logs/images/logs-add-data.png b/docs/logs/images/logs-add-data.png index b7d4fd613edf0..2c4a65590aa1b 100644 Binary files a/docs/logs/images/logs-add-data.png and b/docs/logs/images/logs-add-data.png differ diff --git a/docs/logs/images/logs-configure-source-dialog-add-column-button.png b/docs/logs/images/logs-configure-source-dialog-add-column-button.png deleted file mode 100644 index 2d4c1986d1336..0000000000000 Binary files a/docs/logs/images/logs-configure-source-dialog-add-column-button.png and /dev/null differ diff --git a/docs/logs/images/logs-configure-source-dialog-add-column-popover.png b/docs/logs/images/logs-configure-source-dialog-add-column-popover.png deleted file mode 100644 index b273ab6911b27..0000000000000 Binary files a/docs/logs/images/logs-configure-source-dialog-add-column-popover.png and /dev/null differ diff --git a/docs/logs/images/logs-configure-source-dialog-indices-tab.png b/docs/logs/images/logs-configure-source-dialog-indices-tab.png deleted file mode 100644 index 4f2460debf128..0000000000000 Binary files a/docs/logs/images/logs-configure-source-dialog-indices-tab.png and /dev/null differ diff --git a/docs/logs/images/logs-configure-source-dialog-log-columns-tab.png b/docs/logs/images/logs-configure-source-dialog-log-columns-tab.png deleted file mode 100644 index c89da36d9d9b2..0000000000000 Binary files a/docs/logs/images/logs-configure-source-dialog-log-columns-tab.png and /dev/null differ diff --git a/docs/logs/images/logs-configure-source-gear-icon.png b/docs/logs/images/logs-configure-source-gear-icon.png deleted file mode 100644 index 8b062c627143a..0000000000000 Binary files a/docs/logs/images/logs-configure-source-gear-icon.png and /dev/null differ diff --git a/docs/logs/images/logs-configure-source.png b/docs/logs/images/logs-configure-source.png deleted file mode 100644 index dec6e0ffe11fa..0000000000000 Binary files a/docs/logs/images/logs-configure-source.png and /dev/null differ diff --git a/docs/logs/images/logs-stream-click-entry.png b/docs/logs/images/logs-stream-click-entry.png deleted file mode 100644 index 12705493dce06..0000000000000 Binary files a/docs/logs/images/logs-stream-click-entry.png and /dev/null differ diff --git a/docs/logs/images/logs-stream-filtered-by-value.png b/docs/logs/images/logs-stream-filtered-by-value.png deleted file mode 100644 index af78e1633bf19..0000000000000 Binary files a/docs/logs/images/logs-stream-filtered-by-value.png and /dev/null differ diff --git a/docs/logs/images/logs-stream-highlight-box.png b/docs/logs/images/logs-stream-highlight-box.png deleted file mode 100644 index 1a6cb2b59dd59..0000000000000 Binary files a/docs/logs/images/logs-stream-highlight-box.png and /dev/null differ diff --git a/docs/logs/images/logs-stream-highlight-entries.png b/docs/logs/images/logs-stream-highlight-entries.png deleted file mode 100644 index d23c7c9853304..0000000000000 Binary files a/docs/logs/images/logs-stream-highlight-entries.png and /dev/null differ diff --git a/docs/logs/images/logs-time-selector.png b/docs/logs/images/logs-time-selector.png new file mode 100644 index 0000000000000..5e6a9b7222c54 Binary files /dev/null and b/docs/logs/images/logs-time-selector.png differ diff --git a/docs/logs/images/logs-usage-column-headers.png b/docs/logs/images/logs-usage-column-headers.png deleted file mode 100644 index 7040d5a5c8d00..0000000000000 Binary files a/docs/logs/images/logs-usage-column-headers.png and /dev/null differ diff --git a/docs/logs/images/logs-usage-customize.png b/docs/logs/images/logs-usage-customize.png deleted file mode 100644 index 12089987c6b6e..0000000000000 Binary files a/docs/logs/images/logs-usage-customize.png and /dev/null differ diff --git a/docs/logs/images/logs-usage-query-bar.png b/docs/logs/images/logs-usage-query-bar.png deleted file mode 100644 index 45ba5e4647e18..0000000000000 Binary files a/docs/logs/images/logs-usage-query-bar.png and /dev/null differ diff --git a/docs/logs/images/logs-usage-start-streaming.png b/docs/logs/images/logs-usage-start-streaming.png deleted file mode 100644 index 72221f919b563..0000000000000 Binary files a/docs/logs/images/logs-usage-start-streaming.png and /dev/null differ diff --git a/docs/logs/images/logs-usage-stop-streaming.png b/docs/logs/images/logs-usage-stop-streaming.png deleted file mode 100644 index 77cf9aac596a5..0000000000000 Binary files a/docs/logs/images/logs-usage-stop-streaming.png and /dev/null differ diff --git a/docs/logs/images/logs-usage-streaming-indicator.png b/docs/logs/images/logs-usage-streaming-indicator.png deleted file mode 100644 index 807c0053699ef..0000000000000 Binary files a/docs/logs/images/logs-usage-streaming-indicator.png and /dev/null differ diff --git a/docs/logs/images/logs-usage-time-picker.png b/docs/logs/images/logs-usage-time-picker.png deleted file mode 100644 index 42a0e4d946bb3..0000000000000 Binary files a/docs/logs/images/logs-usage-time-picker.png and /dev/null differ diff --git a/docs/logs/images/logs-usage-timeline.png b/docs/logs/images/logs-usage-timeline.png deleted file mode 100644 index 4ad49f45b3392..0000000000000 Binary files a/docs/logs/images/logs-usage-timeline.png and /dev/null differ diff --git a/docs/logs/images/logs-view-event-with-filter.png b/docs/logs/images/logs-view-event-with-filter.png new file mode 100644 index 0000000000000..4e378af39ab05 Binary files /dev/null and b/docs/logs/images/logs-view-event-with-filter.png differ diff --git a/docs/logs/images/logs-view-event.png b/docs/logs/images/logs-view-event.png new file mode 100644 index 0000000000000..29dff68e3fdba Binary files /dev/null and b/docs/logs/images/logs-view-event.png differ diff --git a/docs/logs/images/read-only-badge.png b/docs/logs/images/read-only-badge.png deleted file mode 100644 index ab7cc296477dc..0000000000000 Binary files a/docs/logs/images/read-only-badge.png and /dev/null differ diff --git a/docs/logs/index.asciidoc b/docs/logs/index.asciidoc index 3c5b9e41fd8e8..77da7197f44a0 100644 --- a/docs/logs/index.asciidoc +++ b/docs/logs/index.asciidoc @@ -4,8 +4,14 @@ [partintro] -- -Use the Logs UI to explore logs for common servers, containers, and services. -{kib} provides a compact, console-like display that you can customize. +The Logs app in Kibana enables you to explore logs for common servers, containers, and services. + +The Logs app has a compact, console-like display that you can customize. +You can filter the logs by various fields, start and stop live streaming, and highlight text of interest. + +You can open the Logs app from the *Logs* tab in Kibana. +You can also open the Logs app directly from a component in the Infrastructure app. +In this case, you will only see the logs for the selected component. * <> * <> diff --git a/docs/logs/using.asciidoc b/docs/logs/using.asciidoc index 21902a94c45b8..cdc990ff1caa0 100644 --- a/docs/logs/using.asciidoc +++ b/docs/logs/using.asciidoc @@ -1,112 +1,79 @@ [role="xpack"] [[xpack-logs-using]] -== Using the Logs UI +== Using the Logs app +Use the Logs app in {kib} to explore and filter your logs in real time. -Customize the Logs UI to focus on the data you want to see and control how you see it. +You can customize the output to focus on the data you want to see and to control how you see it. +You can also view related application traces or uptime information where available. [role="screenshot"] -image::logs/images/logs-console.png[Log Console in Kibana] +image::logs/images/logs-console.png[Logs Console in Kibana] +// ++ Update this [float] [[logs-search]] -=== Use the power of Search -The Search bar is always available. Use it to perform adhoc and structured -searches by taking advantage of the <> with autocompletion -suggestions. +=== Use the power of search -[role="screenshot"] -image::logs/images/logs-usage-query-bar.png[Logs query bar] +Use the search bar to perform ad hoc searches for specific text. +You can also create structured queries using {kibana-ref}/kuery-query.html[Kibana Query Language]. +For example, enter `host.hostname : "host1"` to see only the information for `host1`. +// ++ this isn't quite the same as the corresponding infrastructure description now. [float] [[logs-configure-source]] -=== Adapt to your log source -Using a custom index pattern to store the log entries, want to limit the -entries presented in a space or change the fields displayed in the columns? Use -<> to change the index pattern and -other settings. - -[role="screenshot"] -image::logs/images/logs-usage-column-headers.png[Logs column headers] +=== Configure the data to use for your logs +Are you using a custom index pattern to store the log entries? +Do you want to limit the entries shown or change the fields displayed in the columns? +If so, <> to change the index pattern and other settings. [float] [[logs-time]] -=== Jump to a specific time period -Use the time selector to focus on a specific timeframe. - -[role="screenshot"] -image::logs/images/logs-usage-time-picker.png[Logs time selector] - -To quickly jump to a nearby point in time, click on the timeline to the right. +=== Specify the time and date -[role="screenshot"] -image::logs/images/logs-usage-timeline.png[Logs timeline] +Click the time selector image:logs/images/logs-time-selector.png[time selector icon] to choose the timeframe for the logs. +Log entries for the time you specify appear in the middle of the page, with the earlier entries above and the later entries below. +To quickly jump to a nearby point in time, click the minimap timeline to the right. +// ++ what's this thing called? It's minimap in the UI. Would timeline be better? [float] [[logs-customize]] === Customize your view -Use *Customize* to adjust your console view and to set the time scale of the log data. - -* *Text size.* Select `Small`, `Medium`, or `Large`. -* *Wrap long lines.* Enable or disable line wrap. -* *Minimap Scale.* Set the scale to 'year', 'month', 'week', 'day', 'hour', or 'minute'. - -[role="screenshot"] -image::logs/images/logs-usage-customize.png[Logs view customization popover] +Click *Customize* to customize the view. +Here, you can set the scale to use for the minimap timeline, choose whether to wrap long lines, and choose your preferred text size. [float] [[logs-stream]] === Stream or pause logs -You can stream data for live log tailing, or pause streaming to focus on historical log data. - -[role="screenshot"] -image::logs/images/logs-usage-start-streaming.png[Logs start streaming] +Click *Stream live* to start streaming live log data, or click *Stop streaming* to focus on historical data. -[role="screenshot"] -image::logs/images/logs-usage-stop-streaming.png[Logs stop streaming] - -When you are streaming logs, the most recent log appears at the bottom on the console. - -[role="screenshot"] -image::logs/images/logs-usage-streaming-indicator.png[Logs streaming indicator] +When you are viewing historical data, you can scroll back through the entries as far as there is data available. -Historical data offers infinite scrolling. +When you are streaming live data, the most recent log appears at the bottom of the page. +In live streaming mode, you are not able to choose a different time in the time selector or use the minimap timeline. +To do either of these things, you need to stop live streaming first. +// ++ Not sure whether this is correct or not. And what about just scrolling through the display? +// ++ There may be a bug here, (I managed to get future logs) see https://github.com/elastic/kibana/issues/43361 [float] [[logs-highlight]] === Highlight a phrase in the logs stream -To find instances of a particular word or phrase in the logs stream, click the Highlights button in the toolbar and enter your search terms. - -[role="screenshot"] -image::logs/images/logs-stream-highlight-box.png[Logs highlight dialog box] - -This will highlight any instances of your search terms that appear in the logs stream. - -[role="screenshot"] -image::logs/images/logs-stream-highlight-entries.png[Logs stream with the search term 'safepoint' highlighted] +To highlight a word or phrase in the logs stream, click *Highlights* and enter your search phrase. +// ++ Is search case sensitive? +// ++ Can you search for multiple phrases together, if so, what's the separator? +// ++ What about special characters? For example, I notice that when searching for "Mozilla/4.0" which appears as written in my logs, "Mozilla" is highlighted, as is "4.0" but "/" isn't. The string "-" (which appears in the logs as written, quotes and all, isn't found at all. Any significance? [float] [[logs-event-inspector]] === Inspect a log event -Click on a log event in the stream to inspect it. - -[role="screenshot"] -image::logs/images/logs-stream-click-entry.png[Highlighted log gentry in the stream] +To inspect a log event, hover over it, then click the *View details* icon image:logs/images/logs-view-event.png[View event icon] beside the event. +This opens the *Log event document details* fly-out that shows the fields associated with the log event. -All of the fields associated to the log event are displayed. +To quickly filter the logs stream by one of the field values, click the *View event with filter* icon image:logs/images/logs-view-event-with-filter.png[View event icon] beside the field. +This automatically adds a search filter to the logs stream to filter the entries by this field and value. -[role="screenshot"] -image::logs/images/log-details-flyover.png[Log event document details] +In the log event details, click *Actions* to see the other actions related to the event. +Depending on the event and the features you have installed and configured, you may also be able to: -By clicking the icon next to one of the listed values, you can filter the logs stream to display only events corresponding to that particular value. - -[role="screenshot"] -image::logs/images/log-details-filter.png[Filtering from the log event details] - -[role="screenshot"] -image::logs/images/logs-stream-filtered-by-value.png[Log console after filtering by a value in the details] - -You can use the Actions menu to view any monitor or APM trace that the log event may be associated with. - -[role="screenshot"] -image::logs/images/log-details-actions.png[Log event document details with actions menu open] +* Select *View status in Uptime* to <> in the *Uptime* app. +* Select *View in APM* to <> in the *APM* app. diff --git a/docs/management.asciidoc b/docs/management.asciidoc deleted file mode 100644 index ee8fc0d72e713..0000000000000 --- a/docs/management.asciidoc +++ /dev/null @@ -1,44 +0,0 @@ -[[management]] -= Management - -[partintro] --- -The Management application is where you perform your runtime configuration of -Kibana, including both the initial setup and ongoing configuration of index -patterns, advanced settings that tweak the behaviors of Kibana itself, and -the various "objects" that you can save throughout Kibana such as searches, -visualizations, and dashboards. - --- - -include::management/managing-licenses.asciidoc[] - -include::management/index-patterns.asciidoc[] - -include::management/rollups/create_and_manage_rollups.asciidoc[] - -include::management/index-lifecycle-policies/intro-to-lifecycle-policies.asciidoc[] - -include::management/index-lifecycle-policies/create-policy.asciidoc[] - -include::management/index-lifecycle-policies/manage-policy.asciidoc[] - -include::management/index-lifecycle-policies/add-policy-to-index.asciidoc[] - -include::management/index-lifecycle-policies/example-index-lifecycle-policy.asciidoc[] - -include::management/managing-fields.asciidoc[] - -include::management/managing-indices.asciidoc[] - -include::management/advanced-options.asciidoc[] - -include::management/managing-saved-objects.asciidoc[] - -include::management/managing-beats.asciidoc[] - -include::management/managing-remote-clusters.asciidoc[] - -include::management/snapshot-restore/index.asciidoc[] - - diff --git a/docs/management/managing-saved-objects.asciidoc b/docs/management/managing-saved-objects.asciidoc index caeabd87727d4..324ad46b60554 100644 --- a/docs/management/managing-saved-objects.asciidoc +++ b/docs/management/managing-saved-objects.asciidoc @@ -1,81 +1,83 @@ [[managing-saved-objects]] -== Managing Saved Objects +== Saved objects -You can view, edit, delete, import, and export saved objects from -*Management > Saved Objects*. A saved object can be a search, visualization, -dashboard, or index pattern. +*Saved Objects* helps you keep track of and manage your saved objects. These objects +store data for later use, including dashboards, visualizations, maps, index patterns, +Canvas workpads, and more. + +To get started, go to *Management > {kib} > Saved Objects*. With this UI, you can: + +* <> +* <> +* <> -To narrow the list of saved objects, enter a search term or select an object -type. [role="screenshot"] -image::images/management-saved-objects.png[] +image::images/management-saved-objects.png[Saved Objects] + [float] [[managing-saved-objects-view]] -=== View, edit, and delete objects +=== View, edit, and delete -Each object listed in *Saved Objects* has an *Actions* menu with two items: +* To view and edit an object in its associated application, click the object title. -* *In app* opens the object in its associated application so you can view and -edit it. -* *Relationships* shows other objects that use this object so you know the -impact of deleting it. +* To show objects that use this object, so you know the +impact of deleting it, click the actions icon image:images/actions_icon.png[Actions icon] +and select *Relationships*. -To delete a saved object, select its checkbox and click *Delete*. +* To delete one or more objects, select their checkboxes, and then click *Delete*. [float] -[[managing-saved-objects-object-definition]] -=== Edit an object definition +[[managing-saved-objects-export-objects]] +=== Import and export -*Saved Objects* offers an advanced *Edit* page for modifying the object definition. -To open the page, click the object name in the list of objects. You can change -the object title, add a description, and modify the JSON that defines the -object properties. +Using the import and export commands, you can move objects between different +{kib} instances. This action is useful when you +have multiple environments for development and production. +Import and export also work well when you have a large number +of objects to update and want to batch the process. -If you access an object whose index has been deleted, you can: -* Recreate the index so you can continue using the object. -* Delete the object and recreate it using a different index. -* Change the index name referenced in the object's `kibanaSavedObjectMeta.searchSourceJSON` to point to an existing -index pattern. This is useful if the index you were working with has been renamed. +[float] +==== Import -WARNING: Validation is not performed for object properties. Submitting an invalid -change will render the object unusable. A more failsafe approach is to use the -*Discover*, *Visualize*, or *Dashboard* pages to create new objects instead of -directly editing an existing one. +You can import multiple objects in a single operation. Click *Import* and +navigate to the NDJSON file that +represents the objects to import. By default, +saved objects already in {kib} are overwritten. [float] -[[managing-saved-objects-export-objects]] -=== Export and import objects +==== Export + +You have two options for exporting saved objects. + +* Select the checkboxes of objects that you want to export, and then click *Export*. +* Click *Export x objects*, and export objects by type. -In some cases you might want to export and import a set of save objects. -For example: +This action creates an NDJSON with all your saved objects. By default, +the NDJSON includes related objects. Exported dashboards include their associated index patterns. -* You might have multiple environments for development and production. The export -and import commands allow you to move objects between different {kib} instances. -* You have a large number of objects to update and want to batch this process. -You can export the objects to JSON, make the JSON modification, and re-import -the objects. [float] -==== Export objects +[[managing-saved-objects-object-definition]] +=== Advanced editing -Select the checkboxes of the objects you want to export, and click *Export*. -Or, to export objects by type: +Some objects offer an advanced *Edit* page for modifying the object definition. +To open the page, click the actions icon image:images/actions_icon.png[Actions icon] +and select *Inspect*. +You can change the object title, add a description, and modify +the JSON that defines the object properties. -. Click *Export everything*. -. Select the object types you want to export. -. Click *Export All*. +If you access an object whose index has been deleted, you can: -WARNING: Exported dashboards do not include their associated index patterns. -Re-create the index patterns manually before importing saved dashboards to a -{kib} instance running on another {es} cluster. +* Recreate the index so you can continue using the object. +* Delete the object and recreate it using a different index. +* Change the index name in the object's `reference` array to point to an existing +index pattern. This is useful if the index you were working with has been renamed. -[float] -==== Import objects +WARNING: Validation is not performed for object properties. Submitting an invalid +change will render the object unusable. A more failsafe approach is to use +*Discover*, *Visualize*, or *Dashboard* to create new objects instead of +directly editing an existing one. -. Click *Import*. -. Navigate to the JSON file that represents the objects to import. -. Indicate whether to overwrite objects already in {kib}. -. Click *Import*. \ No newline at end of file diff --git a/docs/maps/connect-to-ems.asciidoc b/docs/maps/connect-to-ems.asciidoc index 75018e6dd4d97..6b4eb9928cea0 100644 --- a/docs/maps/connect-to-ems.asciidoc +++ b/docs/maps/connect-to-ems.asciidoc @@ -4,9 +4,9 @@ https://www.elastic.co/elastic-maps-service[Elastic Maps Service (EMS)] is a service that hosts tile layers and vector shapes of administrative boundaries. -If you are using Kibana's out-of-the-box settings, the **Maps** application is already configured to use EMS. +If you are using Kibana's out-of-the-box settings, **Elastic Maps** is already configured to use EMS. -The **Maps** application makes requests directly from the browser to EMS. +**Elastic Maps** makes requests directly from the browser to EMS. To proxy EMS requests through the Kibana server, set `map.proxyElasticMapsServiceInMaps` to `true` in your <> file. @@ -19,5 +19,5 @@ behind a firewall. If this happens, you can disable the EMS connection to avoid To disable EMS, change your <> file. . Set `map.includeElasticMapsService` to `false` to turn off the EMS connection. -. Set `map.tilemap.url` to the URL of your tile server. This configures the **Maps** default tile layer. +. Set `map.tilemap.url` to the URL of your tile server. This configures the default tile layer of **Elastic Maps**. . (Optional) Set `map.regionmap` to the vector shapes of the administrative boundaries that you want to use. diff --git a/docs/maps/images/create_phrase_filter.png b/docs/maps/images/create_phrase_filter.png new file mode 100644 index 0000000000000..720aecf44d9fa Binary files /dev/null and b/docs/maps/images/create_phrase_filter.png differ diff --git a/docs/maps/images/create_spatial_filter.png b/docs/maps/images/create_spatial_filter.png new file mode 100644 index 0000000000000..abb52bd0b5b0a Binary files /dev/null and b/docs/maps/images/create_spatial_filter.png differ diff --git a/docs/maps/images/filter_icon.png b/docs/maps/images/filter_icon.png new file mode 100644 index 0000000000000..08fd9c6b10a32 Binary files /dev/null and b/docs/maps/images/filter_icon.png differ diff --git a/docs/maps/images/global_search_bar.png b/docs/maps/images/global_search_bar.png index 42445f82db65a..c1bb1e7835e36 100644 Binary files a/docs/maps/images/global_search_bar.png and b/docs/maps/images/global_search_bar.png differ diff --git a/docs/maps/images/global_search_multiple_indices_query1.png b/docs/maps/images/global_search_multiple_indices_query1.png index 7007db3fa0a80..f019f2c4e39d6 100644 Binary files a/docs/maps/images/global_search_multiple_indices_query1.png and b/docs/maps/images/global_search_multiple_indices_query1.png differ diff --git a/docs/maps/images/global_search_multiple_indices_query2.png b/docs/maps/images/global_search_multiple_indices_query2.png index 2a97311114feb..51017039178f1 100644 Binary files a/docs/maps/images/global_search_multiple_indices_query2.png and b/docs/maps/images/global_search_multiple_indices_query2.png differ diff --git a/docs/maps/images/tools_icon.png b/docs/maps/images/tools_icon.png new file mode 100644 index 0000000000000..677b16eb8e484 Binary files /dev/null and b/docs/maps/images/tools_icon.png differ diff --git a/docs/maps/index.asciidoc b/docs/maps/index.asciidoc index cb7ddd62d6c47..bb569a11ed874 100644 --- a/docs/maps/index.asciidoc +++ b/docs/maps/index.asciidoc @@ -1,11 +1,23 @@ [role="xpack"] [[maps]] -= Maps += Elastic Maps [partintro] -- -The **Maps** application enables you to parse through your geographical data at scale, with speed, and in real time. With features like multiple layers and indices in a map, plotting of raw documents, dynamic client-side styling, and global search across multiple layers, you can understand and monitor your data with ease. +*Elastic Maps* enables you to parse through your geographical data at scale, with speed, and in real time. With features like multiple layers and indices in a map, plotting of raw documents, dynamic client-side styling, and global search across multiple layers, you can understand and monitor your data with ease. + +With *Elastic Maps*, you can: + +* Create maps with multiple layers and indices. +* Upload GeoJSON files into Elasticsearch. +* Embed your map in Dashboards. +* Plot individual documents or use aggregations to plot any data set, no matter how large. +* Create choropleth maps. +* Use data driven styling to symbolize features from property values. +* Focus the data you want to display with searches. + +Start your tour of *Elastic Maps* with the <>. [role="screenshot"] image::maps/images/sample_data_ecommerce.png[] diff --git a/docs/maps/maps-getting-started.asciidoc b/docs/maps/maps-getting-started.asciidoc index cec1938881416..f6db2f0fff219 100644 --- a/docs/maps/maps-getting-started.asciidoc +++ b/docs/maps/maps-getting-started.asciidoc @@ -1,8 +1,8 @@ [role="xpack"] [[maps-getting-started]] -== Getting started with Maps +== Getting started with Elastic Maps -You work with *Maps* by adding layers. The data for a layer can come from +You work with *Elastic Maps* by adding layers. The data for a layer can come from sources such as {es} documents, vector sources, tile map services, web map services, and more. You can symbolize the data in different ways. For example, you might show which airports have the longest flight @@ -13,9 +13,8 @@ light to dark. [role="screenshot"] image::maps/images/sample_data_web_logs.png[] -[float] [[maps-read-only-access]] -NOTE: If you have insufficient privileges to create or save maps, a read-only icon +NOTE: If you have insufficient privileges to create or save maps, a read-only icon appears in the application header. The buttons to create new maps or edit existing maps won't be visible. For more information on granting access to Kibana see <>. @@ -26,7 +25,7 @@ image::maps/images/read-only-badge.png[Example of Maps' read only access indicat [float] === Prerequisites Before you start this tutorial, <>. Each -sample data set includes a map to go along with the data. Once you've added the data, open *Maps* and +sample data set includes a map to go along with the data. Once you've added the data, open *Elastic Maps* and explore the different layers of the *[Logs] Total Requests and Bytes* map. You'll re-create this map in this tutorial. @@ -45,7 +44,7 @@ In this tutorial, you'll learn to: The first thing to do is to create a new map. -. If you haven't already, open *Maps*. +. If you haven't already, open *Elastic Maps*. . On the maps list page, click *Create map*. . Set the time range to *Last 7 days*. + diff --git a/docs/maps/search.asciidoc b/docs/maps/search.asciidoc index 33a8ba15113d8..98b8c6ae59c75 100644 --- a/docs/maps/search.asciidoc +++ b/docs/maps/search.asciidoc @@ -2,8 +2,9 @@ [[maps-search]] == Searching your data -The **Maps** application embeds the query bar for real-time ad hoc search. +**Elastic Maps** embeds the search bar for real-time search. Only layers requesting data from {es} are filtered when you submit a search request. +Layers narrowed by the search context contain the filter icon image:maps/images/filter_icon.png[] to the right of layer name in the legend. You can create a layer that requests data from {es} from the following: @@ -13,13 +14,51 @@ You can create a layer that requests data from {es} from the following: ** Grid aggregation source -** <> +** <>. The search context is applied to both the terms join and the vector source when the vector source is provided by Elasticsearch documents. * <> with Grid aggregation source [role="screenshot"] image::maps/images/global_search_bar.png[] +[role="xpack"] +[[maps-create-filter-from-map]] +=== Creating filters from your map + +You can create two types of filters by interacting with your map: + +* <> +* <> + +[float] +[[maps-spatial-filters]] +==== Spatial filters + +A spatial filter narrow searchs results to documents that either intersect with, are within, or do not intersect with the specified geometry. + +You can create spatial filters in two ways: + +* Click the tool icon image:maps/images/tools_icon.png[], and then draw a polygon or bounding box on the map to define the spatial filter. +* Click *Filter by geometry* in a tooltip, and then use the feature's geometry for the spatial filter. ++ +[role="screenshot"] +image::maps/images/create_spatial_filter.png[] + +Spatial filters have the following properties: + +* *Geometry label* enables you to provide a meaningful name for your spatial filter. +* *Spatial field* specifies the geo_point or geo_shape field used to determine if a document matches the spatial relation with the specified geometry. +* *Spatial relation* determines the {ref}/query-dsl-geo-shape-query.html#_spatial_relations[spatial relation operator] to use at search time. Only available when *Spatial field* is set to geo_shape. + +[float] +[[maps-phrase-filter]] +==== Phrase filters + +A phrase filter narrows search results to documents that contain the specified text. +You can create a phrase filter by clicking the plus icon image:maps/images/gs_plus_icon.png[] in a feature tooltip. + +[role="screenshot"] +image::maps/images/create_phrase_filter.png[] [role="xpack"] [[maps-layer-based-filtering]] @@ -43,6 +82,18 @@ This can also occur with a single layer with an {es} source and a <> Searching across multiple indices might sometimes result in empty layers. The most common cause for empty layers are searches for a field that exists in one index, but does not exist in other indices. + +[float] +[[maps-disable-search-for-layer]] +==== Disable search for layer + +To prevent the global search bar from applying search context to a layer, clear the *Apply global filter to layer* checkbox in Layer settings. +Disabling the search context applies to the layer source and all <> configured for the layer. + +[float] +[[maps-add-index-search]] +==== Use _index in your search + Add {ref}/mapping-index-field.html[_index] to your search to include documents from indices that do not contain a search field. For example, suppose you have a vector layer showing the `kibana_sample_data_logs` documents diff --git a/docs/maps/tile-layer.asciidoc b/docs/maps/tile-layer.asciidoc index 1681cd7dcca85..059dd527f4810 100644 --- a/docs/maps/tile-layer.asciidoc +++ b/docs/maps/tile-layer.asciidoc @@ -9,11 +9,11 @@ image::maps/images/tile_layer.png[] You can create a tile layer from the following data sources: -*Custom Tile Map Service*:: Map tiles configured in kibana.yml. +*Configured Tile Map Service*:: Tile map service configured in kibana.yml. See map.tilemap.url in <> for details. -*Tiles*:: Map tiles from https://www.elastic.co/elastic-maps-service[Elastic Maps Service]. +*EMS Basemaps*:: Tile map service from https://www.elastic.co/elastic-maps-service[Elastic Maps Service]. -*Tile Map Service from URL*:: Map tiles from a URL that includes the XYZ coordinates. +*Tile Map Service*:: Tile map service configured in interface. *Web Map Service*:: Maps from OGC Standard WMS. diff --git a/docs/maps/trouble-shooting.asciidoc b/docs/maps/trouble-shooting.asciidoc index d23bed546a6dc..542138828530b 100644 --- a/docs/maps/trouble-shooting.asciidoc +++ b/docs/maps/trouble-shooting.asciidoc @@ -1,13 +1,13 @@ [role="xpack"] [[maps-troubleshooting]] -== Maps troubleshooting +== Elastic Maps troubleshooting Use the information in this section to inspect Elasticsearch requests and find solutions to common problems. [float] === Inspect Elasticsearch requests -The Maps application uses the {ref}/search-search.html[{es} search API] to get documents and aggregation results from {es}. To troubleshoot these requests, open the Inspector, which shows the most recent requests for each layer. You can switch between different requests using the *Request* dropdown. +*Elastic Maps* uses the {ref}/search-search.html[{es} search API] to get documents and aggregation results from {es}. To troubleshoot these requests, open the Inspector, which shows the most recent requests for each layer. You can switch between different requests using the *Request* dropdown. [role="screenshot"] image::maps/images/inspector.png[] diff --git a/docs/maps/vector-layer.asciidoc b/docs/maps/vector-layer.asciidoc index c790107cbd874..8dade1adec6f8 100644 --- a/docs/maps/vector-layer.asciidoc +++ b/docs/maps/vector-layer.asciidoc @@ -9,10 +9,10 @@ image::maps/images/vector_layer.png[] You can create a vector layer from the following sources: -*Custom vector shapes*:: Vector shapes from static files configured in kibana.yml. +*Configured GeoJSON*:: Vector data from hosted GeoJSON configured in kibana.yml. See map.regionmap.* in <> for details. -*Documents*:: Geospatial data from a Kibana index pattern. +*Documents*:: Vector data from a Kibana index pattern. The index must contain at least one field mapped as {ref}/geo-point.html[geo_point] or {ref}/geo-shape.html[geo_shape]. NOTE: Document results are limited to the first 10000 matching documents. @@ -22,7 +22,7 @@ Use <> to plot large data sets. Set *Show as* to *grid rectangles* or *points*. The index must contain at least one field mapped as {ref}/geo-point.html[geo_point]. -*Vector shapes*:: Vector shapes of administrative boundaries from https://www.elastic.co/elastic-maps-service[Elastic Maps Service]. +*EMS Boundaries*:: Administrative boundaries from https://www.elastic.co/elastic-maps-service[Elastic Maps Service]. include::vector-style.asciidoc[] include::vector-style-properties.asciidoc[] diff --git a/docs/migration/migrate_8_0.asciidoc b/docs/migration/migrate_8_0.asciidoc index 43bfec5252eba..a36a93ce31825 100644 --- a/docs/migration/migrate_8_0.asciidoc +++ b/docs/migration/migrate_8_0.asciidoc @@ -74,4 +74,10 @@ specified explicitly. *Impact:* Define `xpack.security.authc.saml.realm` when using the SAML authentication provider instead. -// end::notable-breaking-changes[] \ No newline at end of file +[float] +=== `optimize` directory is now in the `data` folder +*Details:* Generated bundles have moved to the configured `path.data` folder. + +*Impact:* Any workflow that involved manually clearing generated bundles will have to be updated with the new path. + +// end::notable-breaking-changes[] diff --git a/docs/ml/index.asciidoc b/docs/ml/index.asciidoc deleted file mode 100644 index eac51d06a51f9..0000000000000 --- a/docs/ml/index.asciidoc +++ /dev/null @@ -1,77 +0,0 @@ -[role="xpack"] -[[xpack-ml]] -= {ml-cap} - -[partintro] --- - -As datasets increase in size and complexity, the human effort required to -inspect dashboards or maintain rules for spotting infrastructure problems, -cyber attacks, or business issues becomes impractical. The Elastic {ml} -{anomaly-detect} feature automatically models the normal behavior of your time -series data — learning trends, periodicity, and more — in real time to identify -anomalies, streamline root cause analysis, and reduce false positives. - -{anomaly-detect-cap} runs in and scales with {es}, and includes an -intuitive UI on the {kib} *Machine Learning* page for creating {anomaly-jobs} -and understanding results. - -If you have a basic license, you can use the *Data Visualizer* to learn more -about your data. In particular, if your data is stored in {es} and contains a -time field, you can use the *Data Visualizer* to identify possible fields for -{anomaly-detect}: - -[role="screenshot"] -image::ml/images/ml-data-visualizer-sample.jpg[Data Visualizer for sample flight data] - -experimental[] You can also upload a CSV, NDJSON, or log file (up to 100 MB in -size). The *Data Visualizer* identifies the file format and field mappings. You -can then optionally import that data into an {es} index. - -If you have a trial or platinum license, you can -<> and manage jobs and {dfeeds} from the *Job -Management* pane: - -[role="screenshot"] -image::ml/images/ml-job-management.jpg[Job Management] - -You can use the *Settings* pane to create and edit -{stack-ov}/ml-calendars.html[calendars] and the filters that are used in -{stack-ov}/ml-rules.html[custom rules]: - -[role="screenshot"] -image::ml/images/ml-settings.jpg[Calendar Management] - -The *Anomaly Explorer* and *Single Metric Viewer* display the results of your -{anomaly-jobs}. For example: - -[role="screenshot"] -image::ml/images/ml-single-metric-viewer.jpg[Single Metric Viewer] - -You can optionally add annotations by drag-selecting a period of time in -the *Single Metric Viewer* and adding a description. For example, you can add an -explanation for anomalies in that time period or provide notes about what is -occurring in your operational environment at that time: - -[role="screenshot"] -image::ml/images/ml-annotations-list.jpg[Single Metric Viewer with annotations] - -In some circumstances, annotations are also added automatically. For example, if -the {anomaly-job} detects that there is missing data, it annotates the affected -time period. For more information, see -{stack-ov}/ml-delayed-data-detection.html[Handling delayed data]. The -*Job Management* pane shows the full list of annotations for each job. - -NOTE: The {kib} {ml-features} use pop-ups. You must configure your web -browser so that it does not block pop-up windows or create an exception for your -{kib} URL. - -For more information about the {anomaly-detect} feature, see -{stack-ov}/xpack-ml.html[{ml-cap} {anomaly-detect}]. - --- - -include::creating-jobs.asciidoc[] -include::job-tips.asciidoc[] -include::creating-df-kib.asciidoc[] - diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index bfaee1b3ae16e..a8d8a66fd182c 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -24,3 +24,14 @@ For more {kib} configuration settings, see <>. == Uptime security This page has moved. Please see the new section in the {uptime-guide}/uptime-security.html[Uptime Monitoring Guide]. + +[role="exclude",id="infra-read-only-access"] +== Configure source read-only access + +This page has moved. Please see <>. + +[role="exclude",id="logs-read-only-access"] +== Configure source read-only access + +This page has moved. Please see <>. + diff --git a/docs/security/authentication/index.asciidoc b/docs/security/authentication/index.asciidoc index 19a2f5ec4b3a5..1b326c95e20b5 100644 --- a/docs/security/authentication/index.asciidoc +++ b/docs/security/authentication/index.asciidoc @@ -9,6 +9,7 @@ - <> - <> +- <> - <> - <> @@ -44,6 +45,36 @@ The token authentication provider can be used in conjunction with the basic auth xpack.security.authc.providers: [token, basic] -------------------------------------------------------------------------------- +[[pki-authentication]] +==== Public Key Infrastructure (PKI) Authentication + +[IMPORTANT] +============================================================================ +PKI authentication will not work if {kib} is hosted behind a TLS termination reverse proxy. In this configuration, {kib} does not have direct access to the client certificates and cannot authenticate the user. +============================================================================ + +PKI authentication allows users to log into {kib} using X.509 client certificates that must be presented while connecting to {kib}. The certificates must first be accepted for authentication on the {kib} TLS layer, and then they are further validated by an {es} PKI realm. The PKI authentication provider relies on the {es} {ref}/security-api-delegate-pki-authentication.html[Delegate PKI authentication API] to exchange X.509 client certificates to access tokens. All subsequent requests to {es} APIs on behalf of users will be authenticated using these access tokens. + +Prior to configuring {kib}, ensure that the PKI realm is enabled in {es} and configured to permit delegation. See {ref}/configuring-pki-realm.html[Configuring a PKI realm] for more information. + +To enable the PKI authentication provider in {kib}, you must first <>. You must also enable TLS client authentication and include the certificate authority (CA) used to sign client certificates into a list of CAs trusted by {kib} in your `kibana.yml`: + +[source,yaml] +-------------------------------------------------------------------------------- +server.ssl.certificateAuthorities: /path/to/your/cacert.pem +server.ssl.clientAuthentication: required +xpack.security.authc.providers: [pki] +-------------------------------------------------------------------------------- + +PKI support in {kib} is designed to be the primary (or sole) authentication method for users of that {kib} instance. However, you can configure both PKI and Basic authentication for the same {kib} instance: + +[source,yaml] +-------------------------------------------------------------------------------- +xpack.security.authc.providers: [pki, basic] +-------------------------------------------------------------------------------- + +Note that with `server.ssl.clientAuthentication` set to `required`, users are asked to provide a valid client certificate, even if they want to authenticate with username and password. Depending on the security policies, it may or may not be desired. If not, `server.ssl.clientAuthentication` can be set to `optional`. In this case, {kib} still requests a client certificate, but the client won't be required to present one. The `optional` client authentication mode might also be needed in other cases, for example, when PKI authentication is used in conjunction with Reporting. + [[saml]] ==== SAML Single Sign-On diff --git a/docs/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc index 4798dd8678d0a..eac1971b22b17 100644 --- a/docs/settings/reporting-settings.asciidoc +++ b/docs/settings/reporting-settings.asciidoc @@ -83,6 +83,10 @@ Defaults to `120000` (two minutes). Reporting works by capturing screenshots from Kibana. The following settings control the capturing process. +`xpack.reporting.capture.maxAttempts`:: +If capturing a report fails for any reason, Kibana will re-attempt othe reporting +job, as many times as this setting. Defaults to `3`. + `xpack.reporting.capture.loadDelay`:: When visualizations are not evented, this is the amount of time before taking a screenshot. All visualizations that ship with Kibana are evented, so this diff --git a/docs/setup/install/deb.asciidoc b/docs/setup/install/deb.asciidoc index 0bfbccbaed2ba..24e0bb4cf6c18 100644 --- a/docs/setup/install/deb.asciidoc +++ b/docs/setup/install/deb.asciidoc @@ -209,7 +209,7 @@ locations for a Debian-based system: | optimize | Transpiled source code. Certain administrative actions (e.g. plugin install) result in the source code being retranspiled on the fly. - | /usr/share/kibana/optimize + | /var/lib/kibana/optimize d| | plugins diff --git a/docs/setup/install/rpm.asciidoc b/docs/setup/install/rpm.asciidoc index 295ad10206b11..069c50ff87493 100644 --- a/docs/setup/install/rpm.asciidoc +++ b/docs/setup/install/rpm.asciidoc @@ -200,7 +200,7 @@ locations for an RPM-based system: | optimize | Transpiled source code. Certain administrative actions (e.g. plugin install) result in the source code being retranspiled on the fly. - | /usr/share/kibana/optimize + | /var/lib/kibana/optimize d| | plugins diff --git a/docs/setup/install/targz.asciidoc b/docs/setup/install/targz.asciidoc index 3bf48f180783e..138431aca22fa 100644 --- a/docs/setup/install/targz.asciidoc +++ b/docs/setup/install/targz.asciidoc @@ -128,7 +128,7 @@ important data later on. | optimize | Transpiled source code. Certain administrative actions (e.g. plugin install) result in the source code being retranspiled on the fly. - | $KIBANA_HOME\optimize + | $KIBANA_HOME\data\optimize d| | plugins diff --git a/docs/setup/install/windows.asciidoc b/docs/setup/install/windows.asciidoc index b7f695062ae2c..b9f0224e67699 100644 --- a/docs/setup/install/windows.asciidoc +++ b/docs/setup/install/windows.asciidoc @@ -96,7 +96,7 @@ important data later on. | optimize | Transpiled source code. Certain administrative actions (e.g. plugin install) result in the source code being retranspiled on the fly. - | $KIBANA_HOME\optimize + | $KIBANA_HOME\data\optimize d| | plugins diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 336adea0758ab..d354852e9edf0 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -27,10 +27,8 @@ in a manner that is inconsistent with `/proc/self/cgroup` `csp.rules:`:: A template https://w3c.github.io/webappsec-csp/[content-security-policy] that disables -certain unnecessary and potentially insecure capabilities in the browser. All -instances of `{nonce}` will be replaced with an automatically generated nonce -at load time. We strongly recommend that you keep the default CSP rules that -ship with Kibana. +certain unnecessary and potentially insecure capabilities in the browser. We +strongly recommend that you keep the default CSP rules that ship with Kibana. `csp.strict:`:: *Default: `true`* Blocks access to Kibana to any browser that does not enforce even rudimentary CSP rules. In practice, this will disable @@ -295,6 +293,10 @@ files that should be trusted. Details on the format, and the valid options, are available via the https://www.openssl.org/docs/man1.0.2/apps/ciphers.html#CIPHER-LIST-FORMAT[OpenSSL cipher list format documentation]. +`server.ssl.clientAuthentication:`:: *Default: none* Controls the server’s behavior in regard to requesting a certificate from client +connections. Valid values are `required`, `optional`, and `none`. `required` forces a client to present a certificate, while `optional` +requests a client certificate but the client is not required to present one. + `server.ssl.enabled:`:: *Default: "false"* Enables SSL for outgoing requests from the Kibana server to the browser. When set to `true`, `server.ssl.certificate` and `server.ssl.key` are required. diff --git a/docs/siem/images/network-ui.png b/docs/siem/images/network-ui.png index 34cde749cbbb8..a806b8d978991 100644 Binary files a/docs/siem/images/network-ui.png and b/docs/siem/images/network-ui.png differ diff --git a/docs/siem/index.asciidoc b/docs/siem/index.asciidoc index 6d8aea1f7fe63..c947e000c8138 100644 --- a/docs/siem/index.asciidoc +++ b/docs/siem/index.asciidoc @@ -4,8 +4,6 @@ [partintro] -- -coming[7.2] - beta[] The SIEM app in Kibana provides an interactive workspace for security teams to diff --git a/docs/spaces/index.asciidoc b/docs/spaces/index.asciidoc index fdd564cc69c9f..4941861e07097 100644 --- a/docs/spaces/index.asciidoc +++ b/docs/spaces/index.asciidoc @@ -102,7 +102,7 @@ interface to copy objects from one space to another. . (Optional) Delete objects in the export space that you no longer need. {kib} also has experimental <> and -<> dashboard APIs if you want +<> dashboard APIs if you want a dashboard-centric way to automate this process. diff --git a/docs/uptime-guide/deployment-arch.asciidoc b/docs/uptime-guide/deployment-arch.asciidoc new file mode 100644 index 0000000000000..d8edf290b9a5e --- /dev/null +++ b/docs/uptime-guide/deployment-arch.asciidoc @@ -0,0 +1,25 @@ +[role="xpack"] +[[uptime-deployment-arch]] +== Deployment Architecture + +There are multiple ways to deploy Uptime and Heartbeat. +Use the information in this section to determine the best deployment for you. +A guiding principle is that an outage that takes down the service being monitored should not also take down Heartbeat. +You want Heartbeat to be functioning even when your service is not, so the guidelines here help you maximise this possibility. + +Heartbeat is generally run as a centralized service within a data center. +While it is possible to run it as a separate "sidecar" process paired with each process/container, we recommend against it. +Running Heartbeat centrally ensures you will still be able to see monitoring data in the event of an overloaded, disconnected, or otherwise malfunctioning server. + +For further redundancy, you may want to deploy multiple Heartbeats across geographic and/or network boundaries to provide more data. + Specify Heartbeat's observer {heartbeat-ref}/configuration-observer-options.html[geo options] to do so. Some examples might be: + +* **A site served from a content delivery network (CDN) with points of presence (POPs) around the globe:** +In this case you may want to have multiple Heartbeat instances at different data centers around the world checking to see if your site is reachable via local CDN POPs. +* **A service within a single data center that is accessed across multiple VPNs:** +Set up one Heartbeat instance within the VPN the service operates from, and another within an additional VPN that users access the service from. +Having both instances will help pinpoint network errors in the event of an outage. +* **A single service running primarily in a US east coast data center, with a hot failover located in a US west coast data center:** +In each data center, run a Heartbeat instance that checks both the local copy of the service and its counterpart across the country. +Set up two monitors in each region, one for the local service and one for the remote service. +In the event of a data center failure it will be immediately obvious if the service had a connectivity issue to the outside world or if the failure was only internal. diff --git a/docs/uptime-guide/index.asciidoc b/docs/uptime-guide/index.asciidoc index 63f044d43d2a1..7bbc01bb303f1 100644 --- a/docs/uptime-guide/index.asciidoc +++ b/docs/uptime-guide/index.asciidoc @@ -1,11 +1,15 @@ -include::versions.asciidoc[] - -= Uptime monitoring guide +// short-version can be: 8, 7, 6, etc. +:short-version: 8 +include::{asciidoc-dir}/../../shared/versions/stack/{source_branch}.asciidoc[] include::{asciidoc-dir}/../../shared/attributes.asciidoc[] += Uptime monitoring guide + include::overview.asciidoc[] include::install.asciidoc[] +include::deployment-arch.asciidoc[] + include::security.asciidoc[] diff --git a/docs/uptime-guide/versions.asciidoc b/docs/uptime-guide/versions.asciidoc deleted file mode 100644 index 78e07065b81a6..0000000000000 --- a/docs/uptime-guide/versions.asciidoc +++ /dev/null @@ -1,11 +0,0 @@ -// version can be: 7.0.1, 8.0.0-alpha1, etc. -// branch can be: master, 8.0, 8.1, etc. -// major-version can be: 8.x, 7.x, 6.x, etc. -// short-version can be: 8, 7, 6, etc. -// release-state is only: released | prerelease | unreleased - -:version: 8.0.0-alpha1 -:branch: master -:major-version: 8.x -:short-version: 8 -:release-state: prerelease diff --git a/docs/user/api.asciidoc b/docs/user/api.asciidoc new file mode 100644 index 0000000000000..6cd11b2d07123 --- /dev/null +++ b/docs/user/api.asciidoc @@ -0,0 +1,47 @@ +[[api]] += REST API + +[partintro] +-- +Some {kib} features are provided via a REST API, which is ideal for creating an integration with {kib}, or automating +certain aspects of configuring and deploying {kib}. + +Each API has one of the following labels: + +* *Stable* APIs should be safe to use extensively in production. Any breaking +changes to these APIs should only occur in major versions and will be +clearly documented in the breaking changes documentation for that release. + +* *Beta* APIs are on track to become stable, permanent features of {kib}. +Caution should be exercised in their use since it is possible we'd have to make +a breaking change to these APIs in a minor version, but we'll avoid this +wherever possible. + +* *Experimental* APIs are just that - an experiment. An experimental API might +have breaking changes in any version of {kib}, or it might even be removed +entirely. + +If a label is missing from an API, it is considered `experimental`. + +NOTE: You cannot access the APIs via the Console in {kib}. + +[float] +== APIs +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +-- + +include::{kib-repo-dir}/api/features.asciidoc[] +include::{kib-repo-dir}/api/spaces-management.asciidoc[] +include::{kib-repo-dir}/api/role-management.asciidoc[] +include::{kib-repo-dir}/api/saved-objects.asciidoc[] +include::{kib-repo-dir}/api/dashboard-import.asciidoc[] +include::{kib-repo-dir}/api/logstash-configuration-management.asciidoc[] +include::{kib-repo-dir}/api/url-shortening.asciidoc[] +include::{kib-repo-dir}/api/upgrade-assistant.asciidoc[] diff --git a/docs/user/canvas.asciidoc b/docs/user/canvas.asciidoc new file mode 100644 index 0000000000000..f3aa78e8e2e67 --- /dev/null +++ b/docs/user/canvas.asciidoc @@ -0,0 +1,44 @@ +[role="xpack"] +[[canvas]] += Canvas + +[partintro] +-- + +Canvas is a data visualization and presentation tool that sits within Kibana. With Canvas, you can pull live data directly from Elasticsearch, and combine the data with colors, images, text, and your imagination to create dynamic, multi-page, pixel-perfect displays. If you are a little bit creative, a little bit technical, and a whole lot curious, then Canvas is for you. + +With Canvas, you can: + +* Create and personalize your work space with backgrounds, borders, colors, fonts, and more. + +* Customize your workpad with your own visualizations, such as images and text. + +* Customize your data by pulling it directly from Elasticsearch. + +* Show off your data with charts, graphs, progress monitors, and more. + +* Focus the data you want to display with filters. + +[role="screenshot"] +image::images/canvas-gs-example.png[] + +For a quick overview of Canvas, watch link:https://www.youtube.com/watch?v=ZqvF_5-1xjQ[Stand out with Canvas]. +//When https://github.com/elastic/Video/issues/358 is resolved, update this link. + +-- + +include::{kib-repo-dir}/canvas/canvas-tutorial.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-workpad.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-elements.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-present-workpad.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-share-workpad.asciidoc[] + +//include::{kib-repo-dir}/canvas/canvas-expressions.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-function-reference.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-tinymath-functions.asciidoc[] diff --git a/docs/dashboard.asciidoc b/docs/user/dashboard.asciidoc similarity index 98% rename from docs/dashboard.asciidoc rename to docs/user/dashboard.asciidoc index 2b7fd8052f964..1582bf839be12 100644 --- a/docs/dashboard.asciidoc +++ b/docs/user/dashboard.asciidoc @@ -138,7 +138,7 @@ To open an element for editing, put the dashboard in *Edit* mode, and then select *Edit* from the panel menu. The changes you make appear in every dashboard that uses the element. -include::management/dashboard_only_mode/index.asciidoc[] +include::{kib-repo-dir}/management/dashboard_only_mode/index.asciidoc[] diff --git a/docs/user/dev-tools.asciidoc b/docs/user/dev-tools.asciidoc new file mode 100644 index 0000000000000..77a781fd069e4 --- /dev/null +++ b/docs/user/dev-tools.asciidoc @@ -0,0 +1,21 @@ + +[[devtools-kibana]] += Dev Tools + +[partintro] +-- +The *Dev Tools* page contains development tools that you can use to interact +with your data in Kibana. + +* <> +* <> +* <> + + +-- + +include::{kib-repo-dir}/dev-tools/console/console.asciidoc[] + +include::{kib-repo-dir}/dev-tools/searchprofiler/index.asciidoc[] + +include::{kib-repo-dir}/dev-tools/grokdebugger/index.asciidoc[] diff --git a/docs/user/discover.asciidoc b/docs/user/discover.asciidoc new file mode 100644 index 0000000000000..e37f08d0c2692 --- /dev/null +++ b/docs/user/discover.asciidoc @@ -0,0 +1,27 @@ +[[discover]] += Discover + +[partintro] +-- +*Discover* enables you to explore your data with {kib}'s data discovery functions. +You have access to every document in every index that matches the selected index pattern. +You can submit search queries, filter the search results, and view document data. +You can also see the number of documents that match the search query and get field value statistics. +If a time field is configured for the selected index pattern, the distribution of +documents over time is displayed in a histogram at the top of the page. + +[role="screenshot"] +image::images/Discover-Start.png[Discover] +-- + +include::{kib-repo-dir}/discover/set-time-filter.asciidoc[] + +include::{kib-repo-dir}/discover/search.asciidoc[] + +include::{kib-repo-dir}/discover/field-filter.asciidoc[] + +include::{kib-repo-dir}/discover/document-data.asciidoc[] + +include::{kib-repo-dir}/discover/context.asciidoc[] + +include::{kib-repo-dir}/discover/viewing-field-stats.asciidoc[] diff --git a/docs/user/getting-started.asciidoc b/docs/user/getting-started.asciidoc new file mode 100644 index 0000000000000..4d74ca1668327 --- /dev/null +++ b/docs/user/getting-started.asciidoc @@ -0,0 +1,65 @@ +[[getting-started]] += Getting Started + +[partintro] +-- + +You’re new to Kibana and want to give it a try. {kib} has sample data sets and +tutorials to help you get started. + +[float] +=== Sample data + +You can use the <> to take {kib} for a test ride without having +to go through the process of loading data yourself. With one click, +you can install a sample data set and start interacting with +{kib} visualizations in seconds. You can access the sample data +from the {kib} home page. + +[float] + +=== Add data tutorials +{kib} has built-in *Add Data* tutorials to help you set up +data flows in the Elastic Stack. These tutorials are available +from the Kibana home page. In *Add Data to Kibana*, find the data type +you’re interested in, and click its button to view a list of available tutorials. + +[float] +=== Hands-on experience + +The following tutorials walk you through searching, analyzing, +and visualizing data. + +* <>. You'll +learn to filter and query data, edit visualizations, and interact with dashboards. + +* <>. You'll manually load a data set and build +your own visualizations and dashboard. + +[float] +=== Before you begin + +Make sure you've <> and established +a <>. + +If you are running our https://cloud.elastic.co[hosted Elasticsearch Service] +on Elastic Cloud, you can access Kibana with a single click. + + +-- + +include::{kib-repo-dir}/getting-started/add-sample-data.asciidoc[] + +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[] + +include::{kib-repo-dir}/getting-started/tutorial-dashboard.asciidoc[] + diff --git a/docs/user/index.asciidoc b/docs/user/index.asciidoc new file mode 100644 index 0000000000000..3be91b9064576 --- /dev/null +++ b/docs/user/index.asciidoc @@ -0,0 +1,55 @@ +include::introduction.asciidoc[] + +include::setup.asciidoc[] + +include::{kib-repo-dir}/monitoring/configuring-monitoring.asciidoc[] + +include::{kib-repo-dir}/security/securing-kibana.asciidoc[] + +include::getting-started.asciidoc[] + +include::discover.asciidoc[] + +include::visualize.asciidoc[] + +include::dashboard.asciidoc[] + +include::canvas.asciidoc[] + +include::ml/index.asciidoc[] + +include::{kib-repo-dir}/maps/index.asciidoc[] + +include::{kib-repo-dir}/code/index.asciidoc[] + +include::{kib-repo-dir}/infrastructure/index.asciidoc[] + +include::{kib-repo-dir}/logs/index.asciidoc[] + +include::{kib-repo-dir}/apm/index.asciidoc[] + +include::{kib-repo-dir}/uptime/index.asciidoc[] + +include::{kib-repo-dir}/siem/index.asciidoc[] + +include::{kib-repo-dir}/graph/index.asciidoc[] + +include::dev-tools.asciidoc[] + +include::{kib-repo-dir}/monitoring/index.asciidoc[] + +include::management.asciidoc[] + +include::{kib-repo-dir}/spaces/index.asciidoc[] + +include::{kib-repo-dir}/security/index.asciidoc[] + +include::{kib-repo-dir}/management/watcher-ui/index.asciidoc[] + +include::{kib-repo-dir}/management/upgrade-assistant/index.asciidoc[] + +include::{kib-repo-dir}/reporting/index.asciidoc[] + +include::api.asciidoc[] + +include::plugins.asciidoc[] diff --git a/docs/introduction.asciidoc b/docs/user/introduction.asciidoc similarity index 100% rename from docs/introduction.asciidoc rename to docs/user/introduction.asciidoc diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc new file mode 100644 index 0000000000000..d1acb915f1973 --- /dev/null +++ b/docs/user/management.asciidoc @@ -0,0 +1,44 @@ +[[management]] += Management + +[partintro] +-- +The Management application is where you perform your runtime configuration of +Kibana, including both the initial setup and ongoing configuration of index +patterns, advanced settings that tweak the behaviors of Kibana itself, and +the various "objects" that you can save throughout Kibana such as searches, +visualizations, and dashboards. + +-- + +include::{kib-repo-dir}/management/managing-licenses.asciidoc[] + +include::{kib-repo-dir}/management/index-patterns.asciidoc[] + +include::{kib-repo-dir}/management/rollups/create_and_manage_rollups.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[] + +include::{kib-repo-dir}/management/index-lifecycle-policies/manage-policy.asciidoc[] + +include::{kib-repo-dir}/management/index-lifecycle-policies/add-policy-to-index.asciidoc[] + +include::{kib-repo-dir}/management/index-lifecycle-policies/example-index-lifecycle-policy.asciidoc[] + +include::{kib-repo-dir}/management/managing-fields.asciidoc[] + +include::{kib-repo-dir}/management/managing-indices.asciidoc[] + +include::{kib-repo-dir}/management/advanced-options.asciidoc[] + +include::{kib-repo-dir}/management/managing-saved-objects.asciidoc[] + +include::{kib-repo-dir}/management/managing-beats.asciidoc[] + +include::{kib-repo-dir}/management/managing-remote-clusters.asciidoc[] + +include::{kib-repo-dir}/management/snapshot-restore/index.asciidoc[] + + diff --git a/docs/ml/creating-df-kib.asciidoc b/docs/user/ml/creating-df-kib.asciidoc similarity index 93% rename from docs/ml/creating-df-kib.asciidoc rename to docs/user/ml/creating-df-kib.asciidoc index 872c9d5dda8b3..98fb772845a03 100644 --- a/docs/ml/creating-df-kib.asciidoc +++ b/docs/user/ml/creating-df-kib.asciidoc @@ -8,7 +8,7 @@ You can create {stack-ov}/ml-dataframes.html[{dataframe-transforms}] in the {kib} Machine Learning application. [role="screenshot"] -image::ml/images/ml-definepivot.jpg["Defining a {dataframe} pivot"] +image::user/ml/images/ml-definepivot.jpg["Defining a {dataframe} pivot"] Select the index pattern or saved search you want to transform. To pivot your data, you must group the data by at least one field and apply at least one @@ -22,7 +22,7 @@ for the target index. At the end of the process, a {dataframe} job is created as a result. [role="screenshot"] -image::ml/images/ml-jobid.jpg["Job ID and target index"] +image::user/ml/images/ml-jobid.jpg["Job ID and target index"] After you create {dataframe} jobs, you can start, stop, and delete them and explore their progress and statistics from the jobs list. diff --git a/docs/ml/creating-jobs.asciidoc b/docs/user/ml/creating-jobs.asciidoc similarity index 86% rename from docs/ml/creating-jobs.asciidoc rename to docs/user/ml/creating-jobs.asciidoc index 98f175041719a..8eb1ab29897cc 100644 --- a/docs/ml/creating-jobs.asciidoc +++ b/docs/user/ml/creating-jobs.asciidoc @@ -8,7 +8,7 @@ necessary to perform an analytics task. {kib} provides the following wizards to make it easier to create jobs: [role="screenshot"] -image::ml/images/ml-create-job.jpg[Create New Job] +image::user/ml/images/ml-create-job.jpg[Create New Job] A _single metric job_ is a simple job that contains a single _detector_. A detector defines the type of analysis that will occur and which fields to @@ -31,7 +31,7 @@ for that context. For example, if you appears: [role="screenshot"] -image::ml/images/ml-data-recognizer-sample.jpg[A screenshot of the {kib} sample data web log job creation wizard] +image::user/ml/images/ml-data-recognizer-sample.jpg[A screenshot of the {kib} sample data web log job creation wizard] TIP: Alternatively, after you load a sample data set on the {kib} home page, you can click *View data* > *ML jobs*. There are {anomaly-jobs} for both the sample eCommerce orders data set and the sample web logs data set. @@ -43,19 +43,19 @@ http://nginx.org/[Nginx] and https://httpd.apache.org/[Apache] HTTP servers to appear: [role="screenshot"] -image::ml/images/ml-data-recognizer-filebeat.jpg[A screenshot of the {filebeat} job creation wizards] +image::user/ml/images/ml-data-recognizer-filebeat.jpg[A screenshot of the {filebeat} job creation wizards] If you use {auditbeat-ref}/index.html[{auditbeat}] to audit process activity on your systems, the following wizards appear: [role="screenshot"] -image::ml/images/ml-data-recognizer-auditbeat.jpg[A screenshot of the {auditbeat} job creation wizards] +image::user/ml/images/ml-data-recognizer-auditbeat.jpg[A screenshot of the {auditbeat} job creation wizards] Likewise, if you use the {metricbeat-ref}/metricbeat-module-system.html[{metricbeat} system module] to monitor your servers, the following wizards appear: [role="screenshot"] -image::ml/images/ml-data-recognizer-metricbeat.jpg[A screenshot of the {metricbeat} job creation wizards] +image::user/ml/images/ml-data-recognizer-metricbeat.jpg[A screenshot of the {metricbeat} job creation wizards] These wizards create {anomaly-jobs}, dashboards, searches, and visualizations that are customized to help you analyze your {auditbeat}, {filebeat}, and diff --git a/docs/ml/images/ml-annotations-list.jpg b/docs/user/ml/images/ml-annotations-list.jpg similarity index 100% rename from docs/ml/images/ml-annotations-list.jpg rename to docs/user/ml/images/ml-annotations-list.jpg diff --git a/docs/ml/images/ml-create-job.jpg b/docs/user/ml/images/ml-create-job.jpg similarity index 100% rename from docs/ml/images/ml-create-job.jpg rename to docs/user/ml/images/ml-create-job.jpg diff --git a/docs/ml/images/ml-data-recognizer-auditbeat.jpg b/docs/user/ml/images/ml-data-recognizer-auditbeat.jpg similarity index 100% rename from docs/ml/images/ml-data-recognizer-auditbeat.jpg rename to docs/user/ml/images/ml-data-recognizer-auditbeat.jpg diff --git a/docs/ml/images/ml-data-recognizer-filebeat.jpg b/docs/user/ml/images/ml-data-recognizer-filebeat.jpg similarity index 100% rename from docs/ml/images/ml-data-recognizer-filebeat.jpg rename to docs/user/ml/images/ml-data-recognizer-filebeat.jpg diff --git a/docs/ml/images/ml-data-recognizer-metricbeat.jpg b/docs/user/ml/images/ml-data-recognizer-metricbeat.jpg similarity index 100% rename from docs/ml/images/ml-data-recognizer-metricbeat.jpg rename to docs/user/ml/images/ml-data-recognizer-metricbeat.jpg diff --git a/docs/ml/images/ml-data-recognizer-sample.jpg b/docs/user/ml/images/ml-data-recognizer-sample.jpg similarity index 100% rename from docs/ml/images/ml-data-recognizer-sample.jpg rename to docs/user/ml/images/ml-data-recognizer-sample.jpg diff --git a/docs/ml/images/ml-data-visualizer-sample.jpg b/docs/user/ml/images/ml-data-visualizer-sample.jpg similarity index 100% rename from docs/ml/images/ml-data-visualizer-sample.jpg rename to docs/user/ml/images/ml-data-visualizer-sample.jpg diff --git a/docs/ml/images/ml-definepivot.jpg b/docs/user/ml/images/ml-definepivot.jpg similarity index 100% rename from docs/ml/images/ml-definepivot.jpg rename to docs/user/ml/images/ml-definepivot.jpg diff --git a/docs/ml/images/ml-job-management.jpg b/docs/user/ml/images/ml-job-management.jpg similarity index 100% rename from docs/ml/images/ml-job-management.jpg rename to docs/user/ml/images/ml-job-management.jpg diff --git a/docs/ml/images/ml-jobid.jpg b/docs/user/ml/images/ml-jobid.jpg similarity index 100% rename from docs/ml/images/ml-jobid.jpg rename to docs/user/ml/images/ml-jobid.jpg diff --git a/docs/ml/images/ml-settings.jpg b/docs/user/ml/images/ml-settings.jpg similarity index 100% rename from docs/ml/images/ml-settings.jpg rename to docs/user/ml/images/ml-settings.jpg diff --git a/docs/ml/images/ml-single-metric-viewer.jpg b/docs/user/ml/images/ml-single-metric-viewer.jpg similarity index 100% rename from docs/ml/images/ml-single-metric-viewer.jpg rename to docs/user/ml/images/ml-single-metric-viewer.jpg diff --git a/docs/user/ml/index.asciidoc b/docs/user/ml/index.asciidoc new file mode 100644 index 0000000000000..d3ca005d7b62e --- /dev/null +++ b/docs/user/ml/index.asciidoc @@ -0,0 +1,77 @@ +[role="xpack"] +[[xpack-ml]] += {ml-cap} + +[partintro] +-- + +As datasets increase in size and complexity, the human effort required to +inspect dashboards or maintain rules for spotting infrastructure problems, +cyber attacks, or business issues becomes impractical. The Elastic {ml} +{anomaly-detect} feature automatically models the normal behavior of your time +series data — learning trends, periodicity, and more — in real time to identify +anomalies, streamline root cause analysis, and reduce false positives. + +{anomaly-detect-cap} runs in and scales with {es}, and includes an +intuitive UI on the {kib} *Machine Learning* page for creating {anomaly-jobs} +and understanding results. + +If you have a basic license, you can use the *Data Visualizer* to learn more +about your data. In particular, if your data is stored in {es} and contains a +time field, you can use the *Data Visualizer* to identify possible fields for +{anomaly-detect}: + +[role="screenshot"] +image::user/ml/images/ml-data-visualizer-sample.jpg[Data Visualizer for sample flight data] + +experimental[] You can also upload a CSV, NDJSON, or log file (up to 100 MB in +size). The *Data Visualizer* identifies the file format and field mappings. You +can then optionally import that data into an {es} index. + +If you have a trial or platinum license, you can +<> and manage jobs and {dfeeds} from the *Job +Management* pane: + +[role="screenshot"] +image::user/ml/images/ml-job-management.jpg[Job Management] + +You can use the *Settings* pane to create and edit +{stack-ov}/ml-calendars.html[calendars] and the filters that are used in +{stack-ov}/ml-rules.html[custom rules]: + +[role="screenshot"] +image::user/ml/images/ml-settings.jpg[Calendar Management] + +The *Anomaly Explorer* and *Single Metric Viewer* display the results of your +{anomaly-jobs}. For example: + +[role="screenshot"] +image::user/ml/images/ml-single-metric-viewer.jpg[Single Metric Viewer] + +You can optionally add annotations by drag-selecting a period of time in +the *Single Metric Viewer* and adding a description. For example, you can add an +explanation for anomalies in that time period or provide notes about what is +occurring in your operational environment at that time: + +[role="screenshot"] +image::user/ml/images/ml-annotations-list.jpg[Single Metric Viewer with annotations] + +In some circumstances, annotations are also added automatically. For example, if +the {anomaly-job} detects that there is missing data, it annotates the affected +time period. For more information, see +{stack-ov}/ml-delayed-data-detection.html[Handling delayed data]. The +*Job Management* pane shows the full list of annotations for each job. + +NOTE: The {kib} {ml-features} use pop-ups. You must configure your web +browser so that it does not block pop-up windows or create an exception for your +{kib} URL. + +For more information about the {anomaly-detect} feature, see +{stack-ov}/xpack-ml.html[{ml-cap} {anomaly-detect}]. + +-- + +include::creating-jobs.asciidoc[] +include::job-tips.asciidoc[] +include::creating-df-kib.asciidoc[] + diff --git a/docs/ml/job-tips.asciidoc b/docs/user/ml/job-tips.asciidoc similarity index 100% rename from docs/ml/job-tips.asciidoc rename to docs/user/ml/job-tips.asciidoc diff --git a/docs/plugins.asciidoc b/docs/user/plugins.asciidoc similarity index 98% rename from docs/plugins.asciidoc rename to docs/user/plugins.asciidoc index 19c7077c15ffc..e80a81993c4f9 100644 --- a/docs/plugins.asciidoc +++ b/docs/user/plugins.asciidoc @@ -132,4 +132,4 @@ you must specify the path to that configuration file each time you use the `bin/ 74:: I/O error 70:: Other error -include::plugins/known-plugins.asciidoc[] +include::{kib-repo-dir}/plugins/known-plugins.asciidoc[] diff --git a/docs/setup.asciidoc b/docs/user/setup.asciidoc similarity index 79% rename from docs/setup.asciidoc rename to docs/user/setup.asciidoc index ae0e72ed4c649..53e2de66c5287 100644 --- a/docs/setup.asciidoc +++ b/docs/user/setup.asciidoc @@ -46,18 +46,18 @@ encourage users to run the same versions of Kibana and Elasticsearch down to the patch version. -- -include::setup/install.asciidoc[] +include::{kib-repo-dir}/setup/install.asciidoc[] -include::setup/start-stop.asciidoc[] +include::{kib-repo-dir}/setup/start-stop.asciidoc[] -include::setup/settings.asciidoc[] +include::{kib-repo-dir}/setup/settings.asciidoc[] -include::setup/docker.asciidoc[] +include::{kib-repo-dir}/setup/docker.asciidoc[] -include::setup/access.asciidoc[] +include::{kib-repo-dir}/setup/access.asciidoc[] -include::setup/connect-to-elasticsearch.asciidoc[] +include::{kib-repo-dir}/setup/connect-to-elasticsearch.asciidoc[] -include::setup/production.asciidoc[] +include::{kib-repo-dir}/setup/production.asciidoc[] -include::setup/upgrade.asciidoc[] +include::{kib-repo-dir}/setup/upgrade.asciidoc[] diff --git a/docs/visualize.asciidoc b/docs/user/visualize.asciidoc similarity index 87% rename from docs/visualize.asciidoc rename to docs/user/visualize.asciidoc index 535d07cedf7e2..eec9ef65cba90 100644 --- a/docs/visualize.asciidoc +++ b/docs/user/visualize.asciidoc @@ -138,36 +138,36 @@ For more information about working with sub aggregations, see https://www.elastic.co/blog/kibana-aggregation-execution-order-and-you[Kibana, Aggregation Execution Order, and You]. -include::visualize/saving.asciidoc[] +include::{kib-repo-dir}/visualize/saving.asciidoc[] -include::visualize/visualize_rollup_data.asciidoc[] +include::{kib-repo-dir}/visualize/visualize_rollup_data.asciidoc[] -include::visualize/xychart.asciidoc[] +include::{kib-repo-dir}/visualize/xychart.asciidoc[] -include::visualize/controls.asciidoc[] +include::{kib-repo-dir}/visualize/controls.asciidoc[] -include::visualize/datatable.asciidoc[] +include::{kib-repo-dir}/visualize/datatable.asciidoc[] -include::visualize/markdown.asciidoc[] +include::{kib-repo-dir}/visualize/markdown.asciidoc[] -include::visualize/metric.asciidoc[] +include::{kib-repo-dir}/visualize/metric.asciidoc[] -include::visualize/goal.asciidoc[] +include::{kib-repo-dir}/visualize/goal.asciidoc[] -include::visualize/pie.asciidoc[] +include::{kib-repo-dir}/visualize/pie.asciidoc[] -include::visualize/tilemap.asciidoc[] +include::{kib-repo-dir}/visualize/tilemap.asciidoc[] -include::visualize/regionmap.asciidoc[] +include::{kib-repo-dir}/visualize/regionmap.asciidoc[] -include::visualize/timelion.asciidoc[] +include::{kib-repo-dir}/visualize/timelion.asciidoc[] -include::visualize/tsvb.asciidoc[] +include::{kib-repo-dir}/visualize/tsvb.asciidoc[] -include::visualize/tagcloud.asciidoc[] +include::{kib-repo-dir}/visualize/tagcloud.asciidoc[] -include::visualize/heatmap.asciidoc[] +include::{kib-repo-dir}/visualize/heatmap.asciidoc[] -include::visualize/vega.asciidoc[] +include::{kib-repo-dir}/visualize/vega.asciidoc[] -include::visualize/inspector.asciidoc[] +include::{kib-repo-dir}/visualize/inspector.asciidoc[] diff --git a/docs/visualize/timelion.asciidoc b/docs/visualize/timelion.asciidoc index 891219a55e5de..7c7ec7c995ea7 100644 --- a/docs/visualize/timelion.asciidoc +++ b/docs/visualize/timelion.asciidoc @@ -47,7 +47,13 @@ To compare the two data sets, add another series with data from the previous hou [source,text] ---------------------------------- -.es(index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct'), .es(offset=-1h,index=metricbeat-*, timefield='@timestamp', <1> metric='avg:system.cpu.user.pct') +.es(index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct'), + .es(offset=-1h, <1> + index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') ---------------------------------- <1> `offset` offsets the data retrieval by a date expression. In this example, `-1h` offsets the data back by one hour. @@ -81,7 +87,16 @@ Add a meaningful title: [source,text] ---------------------------------- -.es(offset=-1h,index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('last hour'), .es(index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('current hour').title('CPU usage over time') <1> +.es(offset=-1h, + index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('last hour'), +.es(index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('current hour') + .title('CPU usage over time') <1> ---------------------------------- <1> `.title()` adds a title with a meaningful name. Titles make is easier for unfamiliar users to understand the purpose of the visualization. @@ -98,7 +113,17 @@ To differentiate between the current hour data and the last hour data, change th [source,text] ---------------------------------- -.es(offset=-1h,index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('last hour').lines(fill=1,width=0.5), <1> .es(index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('current hour').title('CPU usage over time') +.es(offset=-1h, + index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('last hour') + .lines(fill=1,width=0.5), <1> + .es(index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('current hour') + .title('CPU usage over time') ---------------------------------- <1> `.lines()` changes the appearance of the chart lines. In this example, `.lines(fill=1,width=0.5)` sets the fill level to `1`, and the border width to `0.5`. @@ -115,7 +140,19 @@ To make the current hour data stand out, change the line colors: [source,text] ---------------------------------- -.es(offset=-1h,index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('last hour').lines(fill=1,width=0.5).color(gray), <1> .es(index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('current hour').title('CPU usage over time').color(#1E90FF) +.es(offset=-1h, + index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('last hour') + .lines(fill=1,width=0.5) + .color(gray), <1> +.es(index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('current hour') + .title('CPU usage over time') + .color(#1E90FF) ---------------------------------- <1> `.color()` changes the color of the data. Supported color types include standard color names, hexadecimal values, or a color schema for grouped data. In this example, `.color(gray)` represents the last hour, and `.color(#1E90FF)` represents the current hour. @@ -217,7 +254,25 @@ Customize and format the visualization using functions: [source,text] ---------------------------------- -.es(index=metricbeat*, timefield=@timestamp, metric=max:system.network.in.bytes).derivative().divide(1048576).lines(fill=2, width=1).color(green).label("Inbound traffic").title("Network traffic (MB/s)"), .es(index=metricbeat*, timefield=@timestamp, <1> <2> metric=max:system.network.out.bytes).derivative().multiply(-1).divide(1048576).lines(fill=2, width=1).color(blue)<.label("Outbound <3> <4> traffic").legend(columns=2, position=nw) <5> +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.in.byte) + .derivative() + .divide(1048576) + .lines(fill=2, width=1) + .color(green) + .label("Inbound traffic") <1> + .title("Network traffic (MB/s)"), <2> +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.out.bytes) + .derivative() + .multiply(-1) + .divide(1048576) + .lines(fill=2, width=1) <3> + .color(blue) < <4> + .label("Outbound traffic") + .legend(columns=2, position=nw) <5> ---------------------------------- <1> `.label()` adds custom labels to the visualization. @@ -269,7 +324,31 @@ To track the amount of memory used, create two thresholds: [source,text] ---------------------------------- -.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'), .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').if(gt,11300000000,.es(index=metricbeat-*, timefield='@timestamp', <1> <2> metric='max:system.memory.actual.used.bytes'),null).label('warning').color('#FFCC11'), .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').if(gt,11375000000,.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'),null).label('severe').color('red') +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt, <1> + 11300000000, <2> + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), + null) + .label('warning') + .color('#FFCC11'), + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt, + 11375000000, + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), + null) + .label('severe') + .color('red') ---------------------------------- <1> Timelion conditional logic for the _greater than_ operator. In this example, the warning threshold is 11.3GB (`11300000000`), and the severe threshold is 11.375GB (`11375000000`). If the threshold values are too high or low for your machine, adjust the values accordingly. @@ -304,7 +383,43 @@ Customize and format the visualization using functions: [source,text] ---------------------------------- -.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').label('max memory').title('Memory consumption over time') <1> <2>, .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').if(gt,11300000000,.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'),null).label('warning').color('#FFCC11').lines(width=5), .es(index=metricbeat-*, timefield='@timestamp', <3> <4> metric='max:system.memory.actual.used.bytes').if(gt,11375000000,.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'),null).label('severe').color('red').lines(width=5), .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').mvavg(10).label('mvavg').lines(width=2).color(#5E5E5E).legend(columns=4, position=nw) <5> +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .label('max memory') <1> + .title('Memory consumption over time'), <2> +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt, + 11300000000, + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), + null) + .label('warning') + .color('#FFCC11') <3> + .lines(width=5), <4> + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt, + 11375000000, + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), + null) + .label('severe') + .color('red') + .lines(width=5), + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .mvavg(10) + .label('mvavg') + .lines(width=2) + .color(#5E5E5E) + .legend(columns=4, position=nw) <5> ---------------------------------- <1> `.label()` adds custom labels to the visualization. diff --git a/package.json b/package.json index 0c094878585f0..42b910f248d9a 100644 --- a/package.json +++ b/package.json @@ -44,11 +44,11 @@ "test:quick": "grunt test:quick", "test:browser": "grunt test:browser", "test:jest": "node scripts/jest", - "test:mocha": "grunt test:mocha", + "test:mocha": "node scripts/mocha", + "test:mocha:coverage": "grunt test:mochaCoverage", "test:ui": "node scripts/functional_tests", "test:ui:server": "node scripts/functional_tests_server", "test:ui:runner": "node scripts/functional_test_runner", - "test:server": "echo 'use yarn test:mocha instead'; exit 1", "test:coverage": "grunt test:coverage", "typespec": "typings-tester --config x-pack/legacy/plugins/canvas/public/lib/aeroelastic/tsconfig.json x-pack/legacy/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts", "checkLicenses": "node scripts/check_licenses --dev", @@ -61,7 +61,6 @@ "lint:es": "node scripts/eslint", "lint:sass": "node scripts/sasslint", "makelogs": "node scripts/makelogs", - "mocha": "node scripts/mocha", "uiFramework:start": "cd packages/kbn-ui-framework && yarn docSiteStart", "uiFramework:build": "cd packages/kbn-ui-framework && yarn docSiteBuild", "uiFramework:createComponent": "cd packages/kbn-ui-framework && yarn createComponent", @@ -79,6 +78,7 @@ }, "resolutions": { "**/@types/node": "10.12.27", + "**/@types/react": "16.8.3", "**/@types/hapi": "^17.0.18", "**/typescript": "3.5.3", "**/cypress/lodash": "4.17.13", @@ -101,17 +101,17 @@ ] }, "dependencies": { - "@babel/core": "7.4.5", - "@babel/polyfill": "7.4.4", - "@babel/register": "7.4.4", - "@elastic/charts": "^8.1.6", + "@babel/core": "^7.5.5", + "@babel/register": "^7.5.5", + "@elastic/charts": "^11.1.1", "@elastic/datemath": "5.0.2", - "@elastic/eui": "13.1.1", + "@elastic/eui": "13.8.1", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.3", "@elastic/ui-ace": "0.2.3", "@hapi/wreck": "^15.0.1", + "@kbn/analytics": "1.0.0", "@kbn/babel-code-parser": "1.0.0", "@kbn/babel-preset": "1.0.0", "@kbn/config-schema": "1.0.0", @@ -126,7 +126,7 @@ "@types/react-grid-layout": "^0.16.7", "@types/recompose": "^0.30.5", "JSONStream": "1.3.5", - "abortcontroller-polyfill": "^1.1.9", + "abortcontroller-polyfill": "^1.3.0", "angular": "1.6.9", "angular-aria": "1.6.6", "angular-elastic": "2.5.1", @@ -135,29 +135,30 @@ "angular-sanitize": "1.6.5", "angular-sortable-view": "0.0.17", "autoprefixer": "9.6.1", - "babel-loader": "8.0.6", + "babel-loader": "^8.0.6", "bluebird": "3.5.5", "boom": "^7.2.0", "brace": "0.11.1", - "cache-loader": "^4.0.1", - "chalk": "^2.4.1", + "cache-loader": "^4.1.0", + "chalk": "^2.4.2", "check-disk-space": "^2.1.0", "color": "1.0.3", "commander": "3.0.0", - "compare-versions": "3.4.0", - "core-js": "2.6.9", + "compare-versions": "3.5.1", + "core-js": "^3.2.1", "css-loader": "2.1.1", "custom-event-polyfill": "^0.3.0", "d3": "3.5.17", "d3-cloud": "1.2.5", - "del": "^4.0.0", + "del": "^4.1.1", "elasticsearch": "^16.2.0", "elasticsearch-browser": "^16.2.0", "encode-uri-query": "1.0.1", "execa": "^1.0.0", "expiry-js": "0.1.7", - "file-loader": "4.0.0", + "file-loader": "4.2.0", "font-awesome": "4.7.0", + "fp-ts": "^2.0.5", "getos": "^3.1.0", "glob": "^7.1.2", "glob-all": "^3.1.0", @@ -167,12 +168,14 @@ "handlebars": "4.1.2", "hapi": "^17.5.3", "hapi-auth-cookie": "^9.0.0", + "history": "^4.9.0", "hjson": "3.1.2", "hoek": "^5.0.4", "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", + "https-proxy-agent": "^2.2.2", "inert": "^5.1.0", "inline-style": "^2.0.0", + "io-ts": "^2.0.1", "joi": "^13.5.2", "jquery": "^3.4.1", "js-yaml": "3.13.1", @@ -190,7 +193,7 @@ "lodash.clonedeep": "^4.5.0", "lru-cache": "4.1.5", "markdown-it": "^8.4.1", - "mini-css-extract-plugin": "0.7.0", + "mini-css-extract-plugin": "0.8.0", "minimatch": "^3.0.4", "mkdirp": "0.5.1", "moment": "^2.20.1", @@ -198,7 +201,7 @@ "mustache": "2.3.2", "ngreact": "0.5.1", "node-fetch": "1.7.3", - "opn": "^5.4.0", + "opn": "^5.5.0", "oppsy": "^2.0.0", "pegjs": "0.10.0", "postcss-loader": "3.0.0", @@ -206,7 +209,7 @@ "proxy-from-env": "1.0.0", "pug": "^2.0.3", "querystring-browser": "1.0.4", - "raw-loader": "3.0.0", + "raw-loader": "3.1.0", "react": "^16.8.0", "react-addons-shallow-compare": "15.6.2", "react-color": "^2.13.8", @@ -222,11 +225,12 @@ "redux": "4.0.0", "redux-actions": "2.2.1", "redux-thunk": "2.3.0", + "regenerator-runtime": "^0.13.3", "regression": "2.0.1", "request": "^2.88.0", "reselect": "^3.0.1", "resize-observer-polyfill": "^1.5.0", - "rimraf": "2.6.3", + "rimraf": "2.7.1", "rison-node": "1.0.2", "rxjs": "^6.2.1", "script-loader": "0.7.2", @@ -236,8 +240,8 @@ "style-loader": "0.23.1", "symbol-observable": "^1.2.0", "tar": "4.4.10", - "terser-webpack-plugin": "^1.1.0", - "thread-loader": "^2.1.2", + "terser-webpack-plugin": "^1.4.1", + "thread-loader": "^2.1.3", "tinygradient": "0.4.3", "tinymath": "1.2.1", "topojson-client": "3.0.0", @@ -246,7 +250,7 @@ "tslib": "^1.9.3", "type-detect": "^4.0.8", "ui-select": "0.19.8", - "url-loader": "2.0.0", + "url-loader": "2.1.0", "uuid": "3.3.2", "val-loader": "^1.1.1", "validate-npm-package-name": "2.2.2", @@ -255,18 +259,19 @@ "vega-schema-url-parser": "1.0.0", "vega-tooltip": "^0.9.14", "vision": "^5.3.3", - "webpack": "4.33.0", + "webpack": "4.39.2", "webpack-merge": "4.2.1", "whatwg-fetch": "^3.0.0", "yauzl": "2.10.0" }, "devDependencies": { - "@babel/parser": "7.4.5", + "@babel/parser": "^7.5.5", "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/types": "7.4.4", + "@babel/types": "^7.5.5", "@elastic/eslint-config-kibana": "0.15.0", + "@elastic/eslint-plugin-eui": "0.0.1", "@elastic/github-checks-reporter": "0.0.20b3", - "@elastic/makelogs": "^4.4.0", + "@elastic/makelogs": "^4.5.0", "@kbn/dev-utils": "1.0.0", "@kbn/es": "1.0.0", "@kbn/eslint-import-resolver-kibana": "2.0.0", @@ -278,10 +283,10 @@ "@microsoft/api-documenter": "7.2.1", "@microsoft/api-extractor": "7.1.8", "@octokit/rest": "^15.10.0", - "@percy/agent": "^0.10.0", + "@percy/agent": "^0.11.0", "@types/angular": "1.6.50", "@types/angular-mocks": "^1.7.0", - "@types/babel__core": "^7.1.0", + "@types/babel__core": "^7.1.2", "@types/bluebird": "^3.1.1", "@types/boom": "^7.2.0", "@types/chance": "^1.0.0", @@ -293,9 +298,9 @@ "@types/delete-empty": "^2.0.0", "@types/elasticsearch": "^5.0.33", "@types/enzyme": "^3.9.0", - "@types/eslint": "^4.16.6", + "@types/eslint": "^4.16.8", "@types/execa": "^0.9.0", - "@types/fetch-mock": "7.3.1", + "@types/fetch-mock": "^7.3.1", "@types/getopts": "^2.0.1", "@types/glob": "^7.1.1", "@types/globby": "^8.0.0", @@ -303,6 +308,7 @@ "@types/hapi": "^17.0.18", "@types/hapi-auth-cookie": "^9.1.0", "@types/has-ansi": "^3.0.0", + "@types/history": "^4.7.3", "@types/hoek": "^4.1.3", "@types/humps": "^1.1.2", "@types/jest": "^24.0.9", @@ -316,7 +322,7 @@ "@types/lru-cache": "^5.1.0", "@types/markdown-it": "^0.0.7", "@types/minimatch": "^2.0.29", - "@types/mocha": "^5.2.6", + "@types/mocha": "^5.2.7", "@types/moment-timezone": "^0.5.8", "@types/mustache": "^0.8.31", "@types/node": "^10.12.27", @@ -330,29 +336,29 @@ "@types/react-virtualized": "^9.18.7", "@types/redux": "^3.6.31", "@types/redux-actions": "^2.2.1", - "@types/request": "^2.48.1", + "@types/request": "^2.48.2", "@types/rimraf": "^2.0.2", - "@types/selenium-webdriver": "^3.0.15", + "@types/selenium-webdriver": "^3.0.16", "@types/semver": "^5.5.0", - "@types/sinon": "^7.0.0", + "@types/sinon": "^7.0.13", "@types/strip-ansi": "^3.0.0", - "@types/styled-components": "^3.0.1", + "@types/styled-components": "^3.0.2", "@types/supertest": "^2.0.5", "@types/type-detect": "^4.0.1", "@types/uuid": "^3.4.4", "@types/zen-observable": "^0.8.0", - "@typescript-eslint/eslint-plugin": "1.11.0", - "@typescript-eslint/parser": "1.11.0", + "@typescript-eslint/eslint-plugin": "1.13.0", + "@typescript-eslint/parser": "1.13.0", "angular-mocks": "1.4.7", "archiver": "^3.0.0", - "babel-eslint": "10.0.2", - "babel-jest": "^24.1.0", - "babel-plugin-dynamic-import-node": "^2.2.0", - "backport": "4.6.1", + "babel-eslint": "^10.0.3", + "babel-jest": "^24.9.0", + "babel-plugin-dynamic-import-node": "^2.3.0", + "backport": "4.6.5", "chai": "3.5.0", "chance": "1.0.18", "cheerio": "0.22.0", - "chokidar": "3.0.1", + "chokidar": "3.0.2", "chromedriver": "^76.0.0", "classnames": "2.2.6", "dedent": "^0.7.0", @@ -362,12 +368,12 @@ "enzyme-adapter-utils": "^1.12.0", "enzyme-to-json": "^3.3.4", "eslint": "5.16.0", - "eslint-config-prettier": "6.0.0", - "eslint-plugin-babel": "5.3.0", + "eslint-config-prettier": "6.1.0", + "eslint-plugin-babel": "^5.3.0", "eslint-plugin-ban": "1.2.0", - "eslint-plugin-import": "2.18.0", + "eslint-plugin-import": "2.18.2", "eslint-plugin-jest": "22.7.1", - "eslint-plugin-jsx-a11y": "6.2.1", + "eslint-plugin-jsx-a11y": "6.2.3", "eslint-plugin-mocha": "5.3.0", "eslint-plugin-no-unsanitized": "3.0.2", "eslint-plugin-node": "9.1.0", @@ -375,23 +381,24 @@ "eslint-plugin-prettier": "3.1.0", "eslint-plugin-react": "7.13.0", "eslint-plugin-react-hooks": "1.6.0", - "exit-hook": "^2.1.0", + "exit-hook": "^2.2.0", "faker": "1.1.0", - "fetch-mock": "7.3.3", + "fetch-mock": "^7.3.9", "geckodriver": "1.16.2", "getopts": "^2.2.4", "grunt": "1.0.4", + "grunt-available-tasks": "^0.6.3", "grunt-cli": "^1.2.0", "grunt-contrib-watch": "^1.1.0", "grunt-karma": "2.0.0", "grunt-peg": "^2.0.1", "grunt-run": "0.8.1", - "gulp-babel": "8.0.0", + "gulp-babel": "^8.0.0", "gulp-sourcemaps": "2.6.5", "has-ansi": "^3.0.0", "image-diff": "1.6.3", "intl-messageformat-parser": "^1.4.0", - "is-path-inside": "^2.0.0", + "is-path-inside": "^2.1.0", "istanbul-instrumenter-loader": "3.0.1", "jest": "^24.8.0", "jest-cli": "^24.8.0", @@ -417,6 +424,7 @@ "nock": "10.0.6", "node-sass": "^4.9.4", "normalize-path": "^3.0.0", + "nyc": "^14.1.1", "pixelmatch": "4.0.2", "pkg-up": "^2.0.0", "pngjs": "^3.4.0", @@ -428,7 +436,7 @@ "sass-lint": "^1.12.1", "selenium-webdriver": "^4.0.0-alpha.4", "simple-git": "1.116.0", - "sinon": "^7.2.2", + "sinon": "^7.4.2", "strip-ansi": "^3.0.1", "supertest": "^3.1.0", "supertest-as-promised": "^4.0.2", @@ -437,7 +445,7 @@ "typings-tester": "^0.3.2", "vinyl-fs": "^3.0.2", "xml2js": "^0.4.19", - "xmlbuilder": "9.0.7", + "xmlbuilder": "13.0.2", "zlib": "^1.0.5" }, "engines": { diff --git a/packages/README.md b/packages/README.md index d3b6f9dbf67b6..8ff05f4e8ff89 100644 --- a/packages/README.md +++ b/packages/README.md @@ -49,7 +49,7 @@ Currently there are two patterns used to test packages, one using Mocha and one ### 1. Mocha Today a package can follow the pattern of having a `__tests__` directory in each source code directory of a package which contains the tests for that module. These are usually run by Mocha. -If a package's tests should be run with Mocha, you'll have to opt-in to run them by appending the package's test file pattern(s) to Kibana's `tasks/config/simplemocha.js` file. These will then be run by the unit test runner. +If a package's tests should be run with Mocha, you'll have to opt-in to run them by appending the package's test file pattern(s) to Kibana's `src/dev/mocha/run_mocha_cli.js` file. These will then be run by the unit test runner. * `yarn test` or `yarn grunt test` runs all unit tests. * `node scripts/mocha` runs all Mocha tests. diff --git a/packages/elastic-datemath/__tests__/index.js b/packages/elastic-datemath/__tests__/index.js new file mode 100644 index 0000000000000..6afe09b01ef22 --- /dev/null +++ b/packages/elastic-datemath/__tests__/index.js @@ -0,0 +1,394 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import dateMath from '../src'; +import moment from 'moment'; +import sinon from 'sinon'; +import expect from '@kbn/expect'; + +/** + * Require a new instance of the moment library, bypassing the require cache. + * This is needed, since we are trying to test whether or not this library works + * when passing in a different configured moment instance. If we would change + * the locales on the imported moment, it would automatically apply + * to the source code, even without passing it in to the method, since they share + * the same global state. This method avoids this, by loading a separate instance + * of moment, by deleting the require cache and require the library again. + */ +function momentClone() { + delete require.cache[require.resolve('moment')]; + return require('moment'); +} + +describe('dateMath', function() { + // Test each of these intervals when testing relative time + const spans = ['s', 'm', 'h', 'd', 'w', 'M', 'y', 'ms']; + const anchor = '2014-01-01T06:06:06.666Z'; + const anchoredDate = new Date(Date.parse(anchor)); + const unix = moment(anchor).valueOf(); + const format = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; + let clock; + + describe('errors', function() { + it('should return undefined if passed something falsy', function() { + expect(dateMath.parse()).to.be(undefined); + }); + + it('should return undefined if I pass an operator besides [+-/]', function() { + expect(dateMath.parse('now&1d')).to.be(undefined); + }); + + it('should return undefined if I pass a unit besides' + spans.toString(), function() { + expect(dateMath.parse('now+5f')).to.be(undefined); + }); + + it('should return undefined if rounding unit is not 1', function() { + expect(dateMath.parse('now/2y')).to.be(undefined); + expect(dateMath.parse('now/0.5y')).to.be(undefined); + }); + + it('should not go into an infinite loop when missing a unit', function() { + expect(dateMath.parse('now-0')).to.be(undefined); + expect(dateMath.parse('now-00')).to.be(undefined); + expect(dateMath.parse('now-000')).to.be(undefined); + }); + + describe('forceNow', function() { + it('should throw an Error if passed a string', function() { + const fn = () => dateMath.parse('now', { forceNow: '2000-01-01T00:00:00.000Z' }); + expect(fn).to.throwError(); + }); + + it('should throw an Error if passed a moment', function() { + expect(() => dateMath.parse('now', { forceNow: moment() })).to.throwError(); + }); + + it('should throw an Error if passed an invalid date', function() { + expect(() => dateMath.parse('now', { forceNow: new Date('foobar') })).to.throwError(); + }); + }); + }); + + describe('objects and strings', function() { + let mmnt; + let date; + let string; + let now; + + beforeEach(function() { + clock = sinon.useFakeTimers(unix); + now = moment(); + mmnt = moment(anchor); + date = mmnt.toDate(); + string = mmnt.format(format); + }); + + afterEach(function() { + clock.restore(); + }); + + it('should return the same moment if passed a moment', function() { + expect(dateMath.parse(mmnt)).to.eql(mmnt); + }); + + it('should return a moment if passed a date', function() { + expect(dateMath.parse(date).format(format)).to.eql(mmnt.format(format)); + }); + + it('should return a moment if passed an ISO8601 string', function() { + expect(dateMath.parse(string).format(format)).to.eql(mmnt.format(format)); + }); + + it('should return the current time when parsing now', function() { + expect(dateMath.parse('now').format(format)).to.eql(now.format(format)); + }); + + it('should use the forceNow parameter when parsing now', function() { + expect(dateMath.parse('now', { forceNow: anchoredDate }).valueOf()).to.eql(unix); + }); + }); + + describe('subtraction', function() { + let now; + let anchored; + + beforeEach(function() { + clock = sinon.useFakeTimers(unix); + now = moment(); + anchored = moment(anchor); + }); + + afterEach(function() { + clock.restore(); + }); + + [5, 12, 247].forEach(len => { + spans.forEach(span => { + const nowEx = `now-${len}${span}`; + const thenEx = `${anchor}||-${len}${span}`; + + it('should return ' + len + span + ' ago', function() { + const parsed = dateMath.parse(nowEx).format(format); + expect(parsed).to.eql(now.subtract(len, span).format(format)); + }); + + it('should return ' + len + span + ' before ' + anchor, function() { + const parsed = dateMath.parse(thenEx).format(format); + expect(parsed).to.eql(anchored.subtract(len, span).format(format)); + }); + + it('should return ' + len + span + ' before forceNow', function() { + const parsed = dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf(); + expect(parsed).to.eql(anchored.subtract(len, span).valueOf()); + }); + }); + }); + }); + + describe('addition', function() { + let now; + let anchored; + + beforeEach(function() { + clock = sinon.useFakeTimers(unix); + now = moment(); + anchored = moment(anchor); + }); + + afterEach(function() { + clock.restore(); + }); + + [5, 12, 247].forEach(len => { + spans.forEach(span => { + const nowEx = `now+${len}${span}`; + const thenEx = `${anchor}||+${len}${span}`; + + it('should return ' + len + span + ' from now', function() { + expect(dateMath.parse(nowEx).format(format)).to.eql(now.add(len, span).format(format)); + }); + + it('should return ' + len + span + ' after ' + anchor, function() { + expect(dateMath.parse(thenEx).format(format)).to.eql( + anchored.add(len, span).format(format) + ); + }); + + it('should return ' + len + span + ' after forceNow', function() { + expect(dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf()).to.eql( + anchored.add(len, span).valueOf() + ); + }); + }); + }); + }); + + describe('rounding', function() { + let now; + let anchored; + + beforeEach(function() { + clock = sinon.useFakeTimers(unix); + now = moment(); + anchored = moment(anchor); + }); + + afterEach(function() { + clock.restore(); + }); + + spans.forEach(span => { + it(`should round now to the beginning of the ${span}`, function() { + expect(dateMath.parse('now/' + span).format(format)).to.eql( + now.startOf(span).format(format) + ); + }); + + it(`should round now to the beginning of forceNow's ${span}`, function() { + expect(dateMath.parse('now/' + span, { forceNow: anchoredDate }).valueOf()).to.eql( + anchored.startOf(span).valueOf() + ); + }); + + it(`should round now to the end of the ${span}`, function() { + expect(dateMath.parse('now/' + span, { roundUp: true }).format(format)).to.eql( + now.endOf(span).format(format) + ); + }); + + it(`should round now to the end of forceNow's ${span}`, function() { + expect( + dateMath.parse('now/' + span, { roundUp: true, forceNow: anchoredDate }).valueOf() + ).to.eql(anchored.endOf(span).valueOf()); + }); + }); + }); + + describe('math and rounding', function() { + let now; + let anchored; + + beforeEach(function() { + clock = sinon.useFakeTimers(unix); + now = moment(); + anchored = moment(anchor); + }); + + afterEach(function() { + clock.restore(); + }); + + it('should round to the nearest second with 0 value', function() { + const val = dateMath.parse('now-0s/s').format(format); + expect(val).to.eql(now.startOf('s').format(format)); + }); + + it('should subtract 17s, rounded to the nearest second', function() { + const val = dateMath.parse('now-17s/s').format(format); + expect(val).to.eql( + now + .startOf('s') + .subtract(17, 's') + .format(format) + ); + }); + + it('should add 555ms, rounded to the nearest millisecond', function() { + const val = dateMath.parse('now+555ms/ms').format(format); + expect(val).to.eql( + now + .add(555, 'ms') + .startOf('ms') + .format(format) + ); + }); + + it('should subtract 555ms, rounded to the nearest second', function() { + const val = dateMath.parse('now-555ms/s').format(format); + expect(val).to.eql( + now + .subtract(555, 'ms') + .startOf('s') + .format(format) + ); + }); + + it('should round weeks to Sunday by default', function() { + const val = dateMath.parse('now-1w/w'); + expect(val.isoWeekday()).to.eql(7); + }); + + it('should round weeks based on the passed moment locale start of week setting', function() { + const m = momentClone(); + // Define a locale, that has Tuesday as beginning of the week + m.defineLocale('x-test', { + week: { dow: 2 }, + }); + const val = dateMath.parse('now-1w/w', { momentInstance: m }); + expect(val.isoWeekday()).to.eql(2); + }); + + it('should round up weeks based on the passed moment locale start of week setting', function() { + const m = momentClone(); + // Define a locale, that has Tuesday as beginning of the week + m.defineLocale('x-test', { + week: { dow: 3 }, + }); + const val = dateMath.parse('now-1w/w', { + roundUp: true, + momentInstance: m, + }); + // The end of the range (rounding up) should be the last day of the week (so one day before) + // our start of the week, that's why 3 - 1 + expect(val.isoWeekday()).to.eql(3 - 1); + }); + + it('should round relative to forceNow', function() { + const val = dateMath.parse('now-0s/s', { forceNow: anchoredDate }).valueOf(); + expect(val).to.eql(anchored.startOf('s').valueOf()); + }); + + it('should parse long expressions', () => { + expect(dateMath.parse('now-1d/d+8h+50m')).to.be.ok(); + }); + }); + + describe('used momentjs instance', function() { + it('should use the default moment instance if parameter not specified', function() { + const momentSpy = sinon.spy(moment, 'isMoment'); + dateMath.parse('now'); + expect(momentSpy.called).to.be(true); + momentSpy.restore(); + }); + + it('should not use default moment instance if parameter is specified', function() { + const m = momentClone(); + const momentSpy = sinon.spy(moment, 'isMoment'); + const cloneSpy = sinon.spy(m, 'isMoment'); + dateMath.parse('now', { momentInstance: m }); + expect(momentSpy.called).to.be(false); + expect(cloneSpy.called).to.be(true); + momentSpy.restore(); + cloneSpy.restore(); + }); + + it('should work with multiple different instances', function() { + const m1 = momentClone(); + const m2 = momentClone(); + const m1Spy = sinon.spy(m1, 'isMoment'); + const m2Spy = sinon.spy(m2, 'isMoment'); + dateMath.parse('now', { momentInstance: m1 }); + expect(m1Spy.called).to.be(true); + expect(m2Spy.called).to.be(false); + m1Spy.resetHistory(); + m2Spy.resetHistory(); + dateMath.parse('now', { momentInstance: m2 }); + expect(m1Spy.called).to.be(false); + expect(m2Spy.called).to.be(true); + m1Spy.restore(); + m2Spy.restore(); + }); + + it('should use global instance after passing an instance', function() { + const m = momentClone(); + const momentSpy = sinon.spy(moment, 'isMoment'); + const cloneSpy = sinon.spy(m, 'isMoment'); + dateMath.parse('now', { momentInstance: m }); + expect(momentSpy.called).to.be(false); + expect(cloneSpy.called).to.be(true); + momentSpy.resetHistory(); + cloneSpy.resetHistory(); + dateMath.parse('now'); + expect(momentSpy.called).to.be(true); + expect(cloneSpy.called).to.be(false); + momentSpy.restore(); + cloneSpy.restore(); + }); + }); + + describe('units', function() { + it('should have units descending for unitsDesc', function() { + expect(dateMath.unitsDesc).to.eql(['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']); + }); + + it('should have units ascending for unitsAsc', function() { + expect(dateMath.unitsAsc).to.eql(['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']); + }); + }); +}); diff --git a/packages/elastic-datemath/package.json b/packages/elastic-datemath/package.json index c0e16602a162e..53c8459821147 100644 --- a/packages/elastic-datemath/package.json +++ b/packages/elastic-datemath/package.json @@ -11,9 +11,9 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "7.4.4", - "@babel/preset-env": "7.4.5", - "babel-plugin-add-module-exports": "1.0.2", + "@babel/cli": "^7.5.5", + "@babel/preset-env": "^7.5.5", + "babel-plugin-add-module-exports": "^1.0.2", "moment": "^2.13.0" }, "dependencies": { diff --git a/packages/elastic-datemath/test/index.js b/packages/elastic-datemath/test/index.js deleted file mode 100644 index 582b331eac7e8..0000000000000 --- a/packages/elastic-datemath/test/index.js +++ /dev/null @@ -1,394 +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 dateMath from '../src/index'; -import moment from 'moment'; -import sinon from 'sinon'; -import expect from '@kbn/expect'; - -/** - * Require a new instance of the moment library, bypassing the require cache. - * This is needed, since we are trying to test whether or not this library works - * when passing in a different configured moment instance. If we would change - * the locales on the imported moment, it would automatically apply - * to the source code, even without passing it in to the method, since they share - * the same global state. This method avoids this, by loading a separate instance - * of moment, by deleting the require cache and require the library again. - */ -function momentClone() { - delete require.cache[require.resolve('moment')]; - return require('moment'); -} - -describe('dateMath', function() { - // Test each of these intervals when testing relative time - const spans = ['s', 'm', 'h', 'd', 'w', 'M', 'y', 'ms']; - const anchor = '2014-01-01T06:06:06.666Z'; - const anchoredDate = new Date(Date.parse(anchor)); - const unix = moment(anchor).valueOf(); - const format = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; - let clock; - - describe('errors', function() { - it('should return undefined if passed something falsy', function() { - expect(dateMath.parse()).to.be(undefined); - }); - - it('should return undefined if I pass an operator besides [+-/]', function() { - expect(dateMath.parse('now&1d')).to.be(undefined); - }); - - it('should return undefined if I pass a unit besides' + spans.toString(), function() { - expect(dateMath.parse('now+5f')).to.be(undefined); - }); - - it('should return undefined if rounding unit is not 1', function() { - expect(dateMath.parse('now/2y')).to.be(undefined); - expect(dateMath.parse('now/0.5y')).to.be(undefined); - }); - - it('should not go into an infinite loop when missing a unit', function() { - expect(dateMath.parse('now-0')).to.be(undefined); - expect(dateMath.parse('now-00')).to.be(undefined); - expect(dateMath.parse('now-000')).to.be(undefined); - }); - - describe('forceNow', function() { - it('should throw an Error if passed a string', function() { - const fn = () => dateMath.parse('now', { forceNow: '2000-01-01T00:00:00.000Z' }); - expect(fn).to.throwError(); - }); - - it('should throw an Error if passed a moment', function() { - expect(() => dateMath.parse('now', { forceNow: moment() })).to.throwError(); - }); - - it('should throw an Error if passed an invalid date', function() { - expect(() => dateMath.parse('now', { forceNow: new Date('foobar') })).to.throwError(); - }); - }); - }); - - describe('objects and strings', function() { - let mmnt; - let date; - let string; - let now; - - beforeEach(function() { - clock = sinon.useFakeTimers(unix); - now = moment(); - mmnt = moment(anchor); - date = mmnt.toDate(); - string = mmnt.format(format); - }); - - afterEach(function() { - clock.restore(); - }); - - it('should return the same moment if passed a moment', function() { - expect(dateMath.parse(mmnt)).to.eql(mmnt); - }); - - it('should return a moment if passed a date', function() { - expect(dateMath.parse(date).format(format)).to.eql(mmnt.format(format)); - }); - - it('should return a moment if passed an ISO8601 string', function() { - expect(dateMath.parse(string).format(format)).to.eql(mmnt.format(format)); - }); - - it('should return the current time when parsing now', function() { - expect(dateMath.parse('now').format(format)).to.eql(now.format(format)); - }); - - it('should use the forceNow parameter when parsing now', function() { - expect(dateMath.parse('now', { forceNow: anchoredDate }).valueOf()).to.eql(unix); - }); - }); - - describe('subtraction', function() { - let now; - let anchored; - - beforeEach(function() { - clock = sinon.useFakeTimers(unix); - now = moment(); - anchored = moment(anchor); - }); - - afterEach(function() { - clock.restore(); - }); - - [5, 12, 247].forEach(len => { - spans.forEach(span => { - const nowEx = `now-${len}${span}`; - const thenEx = `${anchor}||-${len}${span}`; - - it('should return ' + len + span + ' ago', function() { - const parsed = dateMath.parse(nowEx).format(format); - expect(parsed).to.eql(now.subtract(len, span).format(format)); - }); - - it('should return ' + len + span + ' before ' + anchor, function() { - const parsed = dateMath.parse(thenEx).format(format); - expect(parsed).to.eql(anchored.subtract(len, span).format(format)); - }); - - it('should return ' + len + span + ' before forceNow', function() { - const parsed = dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf(); - expect(parsed).to.eql(anchored.subtract(len, span).valueOf()); - }); - }); - }); - }); - - describe('addition', function() { - let now; - let anchored; - - beforeEach(function() { - clock = sinon.useFakeTimers(unix); - now = moment(); - anchored = moment(anchor); - }); - - afterEach(function() { - clock.restore(); - }); - - [5, 12, 247].forEach(len => { - spans.forEach(span => { - const nowEx = `now+${len}${span}`; - const thenEx = `${anchor}||+${len}${span}`; - - it('should return ' + len + span + ' from now', function() { - expect(dateMath.parse(nowEx).format(format)).to.eql(now.add(len, span).format(format)); - }); - - it('should return ' + len + span + ' after ' + anchor, function() { - expect(dateMath.parse(thenEx).format(format)).to.eql( - anchored.add(len, span).format(format) - ); - }); - - it('should return ' + len + span + ' after forceNow', function() { - expect(dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf()).to.eql( - anchored.add(len, span).valueOf() - ); - }); - }); - }); - }); - - describe('rounding', function() { - let now; - let anchored; - - beforeEach(function() { - clock = sinon.useFakeTimers(unix); - now = moment(); - anchored = moment(anchor); - }); - - afterEach(function() { - clock.restore(); - }); - - spans.forEach(span => { - it(`should round now to the beginning of the ${span}`, function() { - expect(dateMath.parse('now/' + span).format(format)).to.eql( - now.startOf(span).format(format) - ); - }); - - it(`should round now to the beginning of forceNow's ${span}`, function() { - expect(dateMath.parse('now/' + span, { forceNow: anchoredDate }).valueOf()).to.eql( - anchored.startOf(span).valueOf() - ); - }); - - it(`should round now to the end of the ${span}`, function() { - expect(dateMath.parse('now/' + span, { roundUp: true }).format(format)).to.eql( - now.endOf(span).format(format) - ); - }); - - it(`should round now to the end of forceNow's ${span}`, function() { - expect( - dateMath.parse('now/' + span, { roundUp: true, forceNow: anchoredDate }).valueOf() - ).to.eql(anchored.endOf(span).valueOf()); - }); - }); - }); - - describe('math and rounding', function() { - let now; - let anchored; - - beforeEach(function() { - clock = sinon.useFakeTimers(unix); - now = moment(); - anchored = moment(anchor); - }); - - afterEach(function() { - clock.restore(); - }); - - it('should round to the nearest second with 0 value', function() { - const val = dateMath.parse('now-0s/s').format(format); - expect(val).to.eql(now.startOf('s').format(format)); - }); - - it('should subtract 17s, rounded to the nearest second', function() { - const val = dateMath.parse('now-17s/s').format(format); - expect(val).to.eql( - now - .startOf('s') - .subtract(17, 's') - .format(format) - ); - }); - - it('should add 555ms, rounded to the nearest millisecond', function() { - const val = dateMath.parse('now+555ms/ms').format(format); - expect(val).to.eql( - now - .add(555, 'ms') - .startOf('ms') - .format(format) - ); - }); - - it('should subtract 555ms, rounded to the nearest second', function() { - const val = dateMath.parse('now-555ms/s').format(format); - expect(val).to.eql( - now - .subtract(555, 'ms') - .startOf('s') - .format(format) - ); - }); - - it('should round weeks to Sunday by default', function() { - const val = dateMath.parse('now-1w/w'); - expect(val.isoWeekday()).to.eql(7); - }); - - it('should round weeks based on the passed moment locale start of week setting', function() { - const m = momentClone(); - // Define a locale, that has Tuesday as beginning of the week - m.defineLocale('x-test', { - week: { dow: 2 }, - }); - const val = dateMath.parse('now-1w/w', { momentInstance: m }); - expect(val.isoWeekday()).to.eql(2); - }); - - it('should round up weeks based on the passed moment locale start of week setting', function() { - const m = momentClone(); - // Define a locale, that has Tuesday as beginning of the week - m.defineLocale('x-test', { - week: { dow: 3 }, - }); - const val = dateMath.parse('now-1w/w', { - roundUp: true, - momentInstance: m, - }); - // The end of the range (rounding up) should be the last day of the week (so one day before) - // our start of the week, that's why 3 - 1 - expect(val.isoWeekday()).to.eql(3 - 1); - }); - - it('should round relative to forceNow', function() { - const val = dateMath.parse('now-0s/s', { forceNow: anchoredDate }).valueOf(); - expect(val).to.eql(anchored.startOf('s').valueOf()); - }); - - it('should parse long expressions', () => { - expect(dateMath.parse('now-1d/d+8h+50m')).to.be.ok(); - }); - }); - - describe('used momentjs instance', function() { - it('should use the default moment instance if parameter not specified', function() { - const momentSpy = sinon.spy(moment, 'isMoment'); - dateMath.parse('now'); - expect(momentSpy.called).to.be(true); - momentSpy.restore(); - }); - - it('should not use default moment instance if parameter is specified', function() { - const m = momentClone(); - const momentSpy = sinon.spy(moment, 'isMoment'); - const cloneSpy = sinon.spy(m, 'isMoment'); - dateMath.parse('now', { momentInstance: m }); - expect(momentSpy.called).to.be(false); - expect(cloneSpy.called).to.be(true); - momentSpy.restore(); - cloneSpy.restore(); - }); - - it('should work with multiple different instances', function() { - const m1 = momentClone(); - const m2 = momentClone(); - const m1Spy = sinon.spy(m1, 'isMoment'); - const m2Spy = sinon.spy(m2, 'isMoment'); - dateMath.parse('now', { momentInstance: m1 }); - expect(m1Spy.called).to.be(true); - expect(m2Spy.called).to.be(false); - m1Spy.resetHistory(); - m2Spy.resetHistory(); - dateMath.parse('now', { momentInstance: m2 }); - expect(m1Spy.called).to.be(false); - expect(m2Spy.called).to.be(true); - m1Spy.restore(); - m2Spy.restore(); - }); - - it('should use global instance after passing an instance', function() { - const m = momentClone(); - const momentSpy = sinon.spy(moment, 'isMoment'); - const cloneSpy = sinon.spy(m, 'isMoment'); - dateMath.parse('now', { momentInstance: m }); - expect(momentSpy.called).to.be(false); - expect(cloneSpy.called).to.be(true); - momentSpy.resetHistory(); - cloneSpy.resetHistory(); - dateMath.parse('now'); - expect(momentSpy.called).to.be(true); - expect(cloneSpy.called).to.be(false); - momentSpy.restore(); - cloneSpy.restore(); - }); - }); - - describe('units', function() { - it('should have units descending for unitsDesc', function() { - expect(dateMath.unitsDesc).to.eql(['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']); - }); - - it('should have units ascending for unitsAsc', function() { - expect(dateMath.unitsAsc).to.eql(['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']); - }); - }); -}); diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index 8db516ab4187c..22c6a1a955d57 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -15,14 +15,14 @@ }, "homepage": "https://github.com/elastic/eslint-config-kibana#readme", "peerDependencies": { - "@typescript-eslint/eslint-plugin": "1.12.0", - "@typescript-eslint/parser": "1.12.0", - "babel-eslint": "10.0.2", + "@typescript-eslint/eslint-plugin": "1.13.0", + "@typescript-eslint/parser": "1.13.0", + "babel-eslint": "^10.0.3", "eslint": "5.16.0", - "eslint-plugin-babel": "5.3.0", + "eslint-plugin-babel": "^5.3.0", "eslint-plugin-ban": "1.2.0", - "eslint-plugin-jsx-a11y": "6.2.1", - "eslint-plugin-import": "2.18.0", + "eslint-plugin-jsx-a11y": "6.2.3", + "eslint-plugin-import": "2.18.2", "eslint-plugin-jest": "^22.4.1", "eslint-plugin-mocha": "^5.3.0", "eslint-plugin-no-unsanitized": "3.0.2", diff --git a/packages/kbn-analytics/babel.config.js b/packages/kbn-analytics/babel.config.js new file mode 100644 index 0000000000000..8d5789997625a --- /dev/null +++ b/packages/kbn-analytics/babel.config.js @@ -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. + */ + +// We can't use common Kibana presets here because of babel versions incompatibility +module.exports = { + plugins: ['@babel/plugin-proposal-class-properties'], + env: { + web: { + presets: ['@kbn/babel-preset/webpack_preset'] + }, + node: { + presets: ['@kbn/babel-preset/node_preset'], + }, + }, + ignore: ['**/*.test.ts', '**/*.test.tsx'], +}; diff --git a/packages/kbn-analytics/package.json b/packages/kbn-analytics/package.json index e8fb1aea81a72..e2f3a59e95a47 100644 --- a/packages/kbn-analytics/package.json +++ b/packages/kbn-analytics/package.json @@ -3,19 +3,20 @@ "private": true, "version": "1.0.0", "description": "Kibana Analytics tool", - "main": "target/index.js", - "types": "target/index.d.ts", + "main": "target/node/index.js", + "browser": "target/web/index.js", + "types": "target/types/index.d.ts", "author": "Ahmad Bamieh ", "license": "Apache-2.0", "scripts": { - "build": "tsc", - "kbn:bootstrap": "yarn build", - "kbn:watch": "yarn build --watch" + "build": "node scripts/build", + "kbn:bootstrap": "node scripts/build --source-maps", + "kbn:watch": "node scripts/build --source-maps --watch" }, "devDependencies": { + "@babel/cli": "7.5.5", + "@kbn/dev-utils": "1.0.0", + "@kbn/babel-preset": "1.0.0", "typescript": "3.5.1" - }, - "dependencies": { - "@kbn/dev-utils": "1.0.0" } } diff --git a/packages/kbn-analytics/scripts/build.js b/packages/kbn-analytics/scripts/build.js new file mode 100644 index 0000000000000..3736ab15260fa --- /dev/null +++ b/packages/kbn-analytics/scripts/build.js @@ -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. + */ + +const { resolve } = require('path'); + +const del = require('del'); +const supportsColor = require('supports-color'); +const { run, withProcRunner } = require('@kbn/dev-utils'); + +const ROOT_DIR = resolve(__dirname, '..'); +const BUILD_DIR = resolve(ROOT_DIR, 'target'); + +const padRight = (width, str) => + str.length >= width ? str : `${str}${' '.repeat(width - str.length)}`; + +run( + async ({ log, flags }) => { + await withProcRunner(log, async proc => { + log.info('Deleting old output'); + await del(BUILD_DIR); + + const cwd = ROOT_DIR; + const env = { ...process.env }; + if (supportsColor.stdout) { + env.FORCE_COLOR = 'true'; + } + + log.info(`Starting babel and typescript${flags.watch ? ' in watch mode' : ''}`); + await Promise.all([ + ...['web', 'node'].map(subTask => + proc.run(padRight(10, `babel:${subTask}`), { + cmd: 'babel', + args: [ + 'src', + '--config-file', + require.resolve('../babel.config.js'), + '--out-dir', + resolve(BUILD_DIR, subTask), + '--extensions', + '.ts,.js,.tsx', + ...(flags.watch ? ['--watch'] : ['--quiet']), + ...(flags['source-maps'] ? ['--source-map', 'inline'] : []), + ], + wait: true, + env: { + ...env, + BABEL_ENV: subTask, + }, + cwd, + }) + ), + + proc.run(padRight(10, 'tsc'), { + cmd: 'tsc', + args: [ + '--emitDeclarationOnly', + ...(flags.watch ? ['--watch', '--preserveWatchOutput', 'true'] : []), + ...(flags['source-maps'] ? ['--declarationMap', 'true'] : []), + ], + wait: true, + env, + cwd, + }), + ]); + + log.success('Complete'); + }); + }, + { + description: 'Simple build tool for @kbn/analytics package', + flags: { + boolean: ['watch', 'source-maps'], + help: ` + --watch Run in watch mode + --source-maps Include sourcemaps + `, + }, + } +); diff --git a/packages/kbn-analytics/tsconfig.json b/packages/kbn-analytics/tsconfig.json index fcb8ddbbde68e..fdd9e8281fba8 100644 --- a/packages/kbn-analytics/tsconfig.json +++ b/packages/kbn-analytics/tsconfig.json @@ -2,8 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "declaration": true, - "declarationDir": "./target", - "outDir": "./target", + "declarationDir": "./target/types", "stripInternal": true, "declarationMap": true, "types": [ diff --git a/packages/kbn-babel-code-parser/package.json b/packages/kbn-babel-code-parser/package.json index e6bc157205d0a..a9d373d33ab38 100755 --- a/packages/kbn-babel-code-parser/package.json +++ b/packages/kbn-babel-code-parser/package.json @@ -15,12 +15,12 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "7.4.4" + "@babel/cli": "^7.5.5" }, "dependencies": { "@kbn/babel-preset": "1.0.0", - "@babel/parser": "7.4.5", - "@babel/traverse": "7.4.5", - "lodash": "^4.17.13" + "@babel/parser": "^7.5.5", + "@babel/traverse": "^7.5.5", + "lodash": "^4.17.15" } } diff --git a/packages/kbn-babel-preset/node_preset.js b/packages/kbn-babel-preset/node_preset.js index c4d9193357d78..5ef4219df59f7 100644 --- a/packages/kbn-babel-preset/node_preset.js +++ b/packages/kbn-babel-preset/node_preset.js @@ -17,7 +17,7 @@ * under the License. */ -module.exports = () => { +module.exports = (_, options = {}) => { return { presets: [ [ @@ -32,12 +32,14 @@ module.exports = () => { node: 'current', }, - // replaces `import "@babel/polyfill"` with a list of require statements + // replaces `import "core-js/stable"` with a list of require statements // for just the polyfills that the target versions don't already supply // on their own useBuiltIns: 'entry', modules: 'cjs', - corejs: 2, + corejs: 3, + + ...(options['@babel/preset-env'] || {}) }, ], require('./common_preset'), diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index 0c9f50e11883b..4b18357745360 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -4,13 +4,15 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@babel/plugin-proposal-class-properties": "7.4.4", - "@babel/preset-react":"7.0.0", - "@babel/preset-env": "7.4.5", - "@babel/preset-typescript": "7.3.3", + "@babel/plugin-proposal-class-properties": "^7.5.1", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/preset-env": "^7.5.5", + "@babel/preset-react":"^7.0.0", + "@babel/preset-typescript": "^7.3.3", "@kbn/elastic-idx": "1.0.0", - "babel-plugin-add-module-exports": "1.0.2", - "babel-plugin-transform-define": "1.3.1", - "babel-plugin-typescript-strip-namespaces": "1.1.1" + "babel-plugin-add-module-exports": "^1.0.2", + "babel-plugin-transform-define": "^1.3.1", + "babel-plugin-typescript-strip-namespaces": "^1.1.1" } } diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index a00f5ec556b96..def848f4154bb 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -24,11 +24,15 @@ module.exports = () => { require.resolve('@babel/preset-env'), { useBuiltIns: 'entry', - modules: 'cjs', - corejs: 2, + modules: false, + corejs: 3, }, ], require('./common_preset'), + ], + plugins: [ + require.resolve('@babel/plugin-transform-modules-commonjs'), + require.resolve('@babel/plugin-syntax-dynamic-import'), ] }; }; diff --git a/packages/kbn-config-schema/src/index.ts b/packages/kbn-config-schema/src/index.ts index 4f0a1fc02adf1..210b044421e7e 100644 --- a/packages/kbn-config-schema/src/index.ts +++ b/packages/kbn-config-schema/src/index.ts @@ -36,7 +36,6 @@ import { MapOfOptions, MapOfType, MaybeType, - NullableType, NeverType, NumberOptions, NumberType, @@ -102,7 +101,7 @@ function maybe(type: Type): Type { } function nullable(type: Type): Type { - return new NullableType(type); + return schema.oneOf([type, schema.literal(null)], { defaultValue: null }); } function object

(props: P, options?: ObjectTypeOptions

): ObjectType

{ diff --git a/packages/kbn-config-schema/src/types/__snapshots__/nullable_type.test.ts.snap b/packages/kbn-config-schema/src/types/__snapshots__/nullable_type.test.ts.snap index ae1a34c00d3a8..96ab664921fdf 100644 --- a/packages/kbn-config-schema/src/types/__snapshots__/nullable_type.test.ts.snap +++ b/packages/kbn-config-schema/src/types/__snapshots__/nullable_type.test.ts.snap @@ -1,7 +1,25 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`includes namespace in failure 1`] = `"[foo-namespace]: value is [foo] but it must have a maximum length of [1]."`; +exports[`includes namespace in failure 1`] = ` +"[foo-namespace]: types that failed validation: +- [foo-namespace.0]: value is [foo] but it must have a maximum length of [1]. +- [foo-namespace.1]: expected value to equal [null] but got [foo]" +`; -exports[`validates basic type 1`] = `"expected value of type [string] but got [number]"`; +exports[`validates basic type 1`] = ` +"types that failed validation: +- [0]: expected value of type [string] but got [number] +- [1]: expected value to equal [null] but got [666]" +`; -exports[`validates contained type 1`] = `"value is [foo] but it must have a maximum length of [1]."`; +exports[`validates contained type 1`] = ` +"types that failed validation: +- [0]: value is [foo] but it must have a maximum length of [1]. +- [1]: expected value to equal [null] but got [foo]" +`; + +exports[`validates type errors in object 1`] = ` +"[foo]: types that failed validation: +- [foo.0]: value is [ab] but it must have a maximum length of [1]. +- [foo.1]: expected value to equal [null] but got [ab]" +`; diff --git a/packages/kbn-config-schema/src/types/index.ts b/packages/kbn-config-schema/src/types/index.ts index 4c25cade2ec61..cfa8cc4b7553d 100644 --- a/packages/kbn-config-schema/src/types/index.ts +++ b/packages/kbn-config-schema/src/types/index.ts @@ -26,7 +26,6 @@ export { ConditionalType, ConditionalTypeValue } from './conditional_type'; export { DurationOptions, DurationType } from './duration_type'; export { LiteralType } from './literal_type'; export { MaybeType } from './maybe_type'; -export { NullableType } from './nullable_type'; export { MapOfOptions, MapOfType } from './map_type'; export { NumberOptions, NumberType } from './number_type'; export { ObjectType, ObjectTypeOptions, Props, TypeOf } from './object_type'; diff --git a/packages/kbn-config-schema/src/types/nullable_type.test.ts b/packages/kbn-config-schema/src/types/nullable_type.test.ts index e9d6f3ca2fe35..ed04202950a2c 100644 --- a/packages/kbn-config-schema/src/types/nullable_type.test.ts +++ b/packages/kbn-config-schema/src/types/nullable_type.test.ts @@ -19,19 +19,66 @@ import { schema } from '..'; -test('returns value if specified', () => { +test('returns string value when passed string', () => { const type = schema.nullable(schema.string()); - expect(type.validate('test')).toEqual('test'); + expect(type.validate('test')).toBe('test'); }); -test('returns null if null', () => { +test('returns number value when passed number', () => { + const type = schema.nullable(schema.number()); + expect(type.validate(42)).toBe(42); +}); + +test('returns boolean value when passed boolean', () => { + const type = schema.nullable(schema.boolean()); + expect(type.validate(true)).toBe(true); +}); + +test('returns object value when passed object', () => { + const type = schema.nullable( + schema.object({ + foo: schema.number(), + bar: schema.boolean(), + baz: schema.string(), + }) + ); + const object = { + foo: 666, + bar: true, + baz: 'foo bar baz', + }; + + expect(type.validate(object)).toEqual(object); +}); + +test('returns null if null for string', () => { const type = schema.nullable(schema.string()); - expect(type.validate(null)).toEqual(null); + expect(type.validate(null)).toBe(null); +}); + +test('returns null if null for number', () => { + const type = schema.nullable(schema.number()); + expect(type.validate(null)).toBe(null); }); -test('returns null if undefined', () => { +test('returns null if null for boolean', () => { + const type = schema.nullable(schema.boolean()); + expect(type.validate(null)).toBe(null); +}); + +test('returns null if undefined for string', () => { const type = schema.nullable(schema.string()); - expect(type.validate(undefined)).toEqual(null); + expect(type.validate(undefined)).toBe(null); +}); + +test('returns null if undefined for number', () => { + const type = schema.nullable(schema.number()); + expect(type.validate(undefined)).toBe(null); +}); + +test('returns null if undefined for boolean', () => { + const type = schema.nullable(schema.boolean()); + expect(type.validate(undefined)).toBe(null); }); test('returns null even if contained type has a default value', () => { @@ -41,7 +88,7 @@ test('returns null even if contained type has a default value', () => { }) ); - expect(type.validate(undefined)).toEqual(null); + expect(type.validate(undefined)).toBe(null); }); test('validates contained type', () => { @@ -56,6 +103,27 @@ test('validates basic type', () => { expect(() => type.validate(666)).toThrowErrorMatchingSnapshot(); }); +test('validates type in object', () => { + const type = schema.object({ + foo: schema.nullable(schema.string({ maxLength: 1 })), + bar: schema.nullable(schema.boolean()), + }); + + expect(type.validate({ foo: 'a' })).toEqual({ foo: 'a', bar: null }); + expect(type.validate({ foo: null })).toEqual({ foo: null, bar: null }); + expect(type.validate({})).toEqual({ foo: null, bar: null }); + expect(type.validate({ bar: null })).toEqual({ foo: null, bar: null }); +}); + +test('validates type errors in object', () => { + const type = schema.object({ + foo: schema.nullable(schema.string({ maxLength: 1 })), + bar: schema.nullable(schema.boolean()), + }); + + expect(() => type.validate({ foo: 'ab' })).toThrowErrorMatchingSnapshot(); +}); + test('includes namespace in failure', () => { const type = schema.nullable(schema.string({ maxLength: 1 })); diff --git a/packages/kbn-config-schema/src/types/nullable_type.ts b/packages/kbn-config-schema/src/types/nullable_type.ts deleted file mode 100644 index c89f3e44c37c4..0000000000000 --- a/packages/kbn-config-schema/src/types/nullable_type.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 { Type } from './type'; - -export class NullableType extends Type { - constructor(type: Type) { - super( - type - .getSchema() - .optional() - .allow(null) - .default(null) - ); - } -} diff --git a/packages/kbn-dev-utils/.babelrc b/packages/kbn-dev-utils/.babelrc deleted file mode 100644 index 7da72d1779128..0000000000000 --- a/packages/kbn-dev-utils/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@kbn/babel-preset/node_preset"] -} diff --git a/packages/kbn-dev-utils/src/certs/ca.crt b/packages/kbn-dev-utils/certs/ca.crt similarity index 100% rename from packages/kbn-dev-utils/src/certs/ca.crt rename to packages/kbn-dev-utils/certs/ca.crt diff --git a/packages/kbn-dev-utils/src/certs/elasticsearch.crt b/packages/kbn-dev-utils/certs/elasticsearch.crt similarity index 100% rename from packages/kbn-dev-utils/src/certs/elasticsearch.crt rename to packages/kbn-dev-utils/certs/elasticsearch.crt diff --git a/packages/kbn-dev-utils/src/certs/elasticsearch.key b/packages/kbn-dev-utils/certs/elasticsearch.key similarity index 100% rename from packages/kbn-dev-utils/src/certs/elasticsearch.key rename to packages/kbn-dev-utils/certs/elasticsearch.key diff --git a/packages/kbn-dev-utils/index.d.ts b/packages/kbn-dev-utils/index.d.ts deleted file mode 100644 index dceadb9496f3b..0000000000000 --- a/packages/kbn-dev-utils/index.d.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 * from './src/tooling_log'; -export * from './src/serializers'; diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index 71c7d2e311017..2e7e4c5500a3c 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -1,26 +1,27 @@ { "name": "@kbn/dev-utils", "main": "./target/index.js", - "types": "./index.d.ts", "version": "1.0.0", "license": "Apache-2.0", "private": true, "scripts": { - "build": "babel src --out-dir target --copy-files", - "kbn:bootstrap": "yarn build --quiet", + "build": "tsc", + "kbn:bootstrap": "yarn build", "kbn:watch": "yarn build --watch" }, "dependencies": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", + "dedent": "^0.7.0", "execa": "^1.0.0", + "exit-hook": "^2.2.0", + "getopts": "^2.2.5", "moment": "^2.20.1", "rxjs": "^6.2.1", "tree-kill": "^1.2.0", "tslib": "^1.9.3" }, "devDependencies": { - "@babel/cli": "7.4.4", - "@kbn/babel-preset": "1.0.0", + "typescript": "3.5.3", "@kbn/expect": "1.0.0", "chance": "1.0.18" } diff --git a/packages/kbn-dev-utils/src/certs.ts b/packages/kbn-dev-utils/src/certs.ts new file mode 100644 index 0000000000000..0d340e4e8c906 --- /dev/null +++ b/packages/kbn-dev-utils/src/certs.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'; + +export const CA_CERT_PATH = resolve(__dirname, '../certs/ca.crt'); +export const ES_KEY_PATH = resolve(__dirname, '../certs/elasticsearch.key'); +export const ES_CERT_PATH = resolve(__dirname, '../certs/elasticsearch.crt'); diff --git a/packages/kbn-dev-utils/src/certs/index.js b/packages/kbn-dev-utils/src/certs/index.js deleted file mode 100644 index 97292eec3512b..0000000000000 --- a/packages/kbn-dev-utils/src/certs/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. - */ - -import { resolve } from 'path'; - -export const CA_CERT_PATH = resolve(__dirname, 'ca.crt'); -export const ES_KEY_PATH = resolve(__dirname, 'elasticsearch.key'); -export const ES_CERT_PATH = resolve(__dirname, 'elasticsearch.crt'); diff --git a/packages/kbn-dev-utils/src/constants.ts b/packages/kbn-dev-utils/src/constants.ts new file mode 100644 index 0000000000000..5d3b57509715e --- /dev/null +++ b/packages/kbn-dev-utils/src/constants.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. + */ + +import { dirname } from 'path'; + +export const REPO_ROOT = dirname(require.resolve('../../../package.json')); diff --git a/packages/kbn-dev-utils/src/index.js b/packages/kbn-dev-utils/src/index.js deleted file mode 100644 index cba24575bd39c..0000000000000 --- a/packages/kbn-dev-utils/src/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 { withProcRunner } from './proc_runner'; -export { ToolingLog, ToolingLogTextWriter, pickLevelFromFlags } from './tooling_log'; -export { createAbsolutePathSerializer } from './serializers'; -export { CA_CERT_PATH, ES_KEY_PATH, ES_CERT_PATH } from './certs'; diff --git a/packages/kbn-dev-utils/src/index.ts b/packages/kbn-dev-utils/src/index.ts new file mode 100644 index 0000000000000..6d3914eb56218 --- /dev/null +++ b/packages/kbn-dev-utils/src/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. + */ + +export { withProcRunner } from './proc_runner'; +export { ToolingLog, ToolingLogTextWriter, pickLevelFromFlags } from './tooling_log'; +export { createAbsolutePathSerializer } from './serializers'; +export { CA_CERT_PATH, ES_KEY_PATH, ES_CERT_PATH } from './certs'; +export { run, createFailError, createFlagError, combineErrors, isFailError, Flags } from './run'; +export { REPO_ROOT } from './constants'; diff --git a/packages/kbn-dev-utils/src/proc_runner/errors.js b/packages/kbn-dev-utils/src/proc_runner/errors.js deleted file mode 100644 index 9374e77f49f4e..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/errors.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. - */ - -const $isCliError = Symbol('isCliError'); - -export function createCliError(message) { - const error = new Error(message); - error[$isCliError] = true; - return error; -} - -export function isCliError(error) { - return error && !!error[$isCliError]; -} diff --git a/packages/kbn-dev-utils/src/proc_runner/errors.ts b/packages/kbn-dev-utils/src/proc_runner/errors.ts new file mode 100644 index 0000000000000..590d9ed76e1fc --- /dev/null +++ b/packages/kbn-dev-utils/src/proc_runner/errors.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. + */ + +const $isCliError = Symbol('isCliError'); + +interface CliError extends Error { + [$isCliError]: boolean; +} + +export function createCliError(message: string) { + const error: Partial = new Error(message); + error[$isCliError] = true; + return error as CliError; +} + +export function isCliError(error: any): error is CliError { + return error && !!error[$isCliError]; +} diff --git a/packages/kbn-dev-utils/src/proc_runner/index.js b/packages/kbn-dev-utils/src/proc_runner/index.ts similarity index 100% rename from packages/kbn-dev-utils/src/proc_runner/index.js rename to packages/kbn-dev-utils/src/proc_runner/index.ts diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_lines.js b/packages/kbn-dev-utils/src/proc_runner/observe_lines.js deleted file mode 100644 index 586353faef3e9..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/observe_lines.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 * as Rx from 'rxjs'; -import { scan, takeUntil, share, materialize, mergeMap, last, catchError } from 'rxjs/operators'; - -const SEP = /\r?\n/; - -import { observeReadable } from './observe_readable'; - -/** - * Creates an Observable from a Readable Stream that: - * - splits data from `readable` into lines - * - completes when `readable` emits "end" - * - fails if `readable` emits "errors" - * - * @param {ReadableStream} readable - * @return {Rx.Observable} - */ -export function observeLines(readable) { - const done$ = observeReadable(readable).pipe(share()); - - const scan$ = Rx.fromEvent(readable, 'data').pipe( - scan( - ({ buffer }, chunk) => { - buffer += chunk; - - let match; - const lines = []; - while ((match = buffer.match(SEP))) { - lines.push(buffer.slice(0, match.index)); - buffer = buffer.slice(match.index + match[0].length); - } - - return { buffer, lines }; - }, - { buffer: '' } - ), - - // stop if done completes or errors - takeUntil(done$.pipe(materialize())) - ); - - return Rx.merge( - // use done$ to provide completion/errors - done$, - - // merge in the "lines" from each step - scan$.pipe(mergeMap(({ lines }) => lines)), - - // inject the "unsplit" data at the end - scan$.pipe( - last(), - mergeMap(({ buffer }) => (buffer ? [buffer] : [])), - // if there were no lines, last() will error, so catch and complete - catchError(() => Rx.empty()) - ) - ); -} diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_lines.ts b/packages/kbn-dev-utils/src/proc_runner/observe_lines.ts new file mode 100644 index 0000000000000..fc446a7a81adc --- /dev/null +++ b/packages/kbn-dev-utils/src/proc_runner/observe_lines.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 { Readable } from 'stream'; + +import * as Rx from 'rxjs'; +import { scan, takeUntil, share, materialize, mergeMap, last, catchError } from 'rxjs/operators'; + +const SEP = /\r?\n/; + +import { observeReadable } from './observe_readable'; + +/** + * Creates an Observable from a Readable Stream that: + * - splits data from `readable` into lines + * - completes when `readable` emits "end" + * - fails if `readable` emits "errors" + * + * @param {ReadableStream} readable + * @return {Rx.Observable} + */ +export function observeLines(readable: Readable): Rx.Observable { + const done$ = observeReadable(readable).pipe(share()); + + const scan$: Rx.Observable<{ buffer: string; lines?: string[] }> = Rx.fromEvent( + readable, + 'data' + ).pipe( + scan( + ({ buffer }, chunk) => { + buffer += chunk; + + const lines = []; + while (true) { + const match = buffer.match(SEP); + + if (!match || match.index === undefined) { + break; + } + + lines.push(buffer.slice(0, match.index)); + buffer = buffer.slice(match.index + match[0].length); + } + + return { buffer, lines }; + }, + { buffer: '' } + ), + + // stop if done completes or errors + takeUntil(done$.pipe(materialize())), + + share() + ); + + return Rx.merge( + // use done$ to provide completion/errors + done$, + + // merge in the "lines" from each step + scan$.pipe(mergeMap(({ lines }) => lines || [])), + + // inject the "unsplit" data at the end + scan$.pipe( + last(), + mergeMap(({ buffer }) => (buffer ? [buffer] : [])), + // if there were no lines, last() will error, so catch and complete + catchError(() => Rx.empty()) + ) + ); +} diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_readable.js b/packages/kbn-dev-utils/src/proc_runner/observe_readable.js deleted file mode 100644 index cb572ff46b318..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/observe_readable.js +++ /dev/null @@ -1,43 +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 { first, ignoreElements, map } from 'rxjs/operators'; - -/** - * Produces an Observable from a ReadableSteam that: - * - completes on the first "end" event - * - fails on the first "error" event - * - * @param {ReadableStream} readable - * @return {Rx.Observable} - */ -export function observeReadable(readable) { - return Rx.race( - Rx.fromEvent(readable, 'end').pipe( - first(), - ignoreElements() - ), - - Rx.fromEvent(readable, 'error').pipe( - first(), - map(err => Rx.throwError(err)) - ) - ); -} diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_readable.ts b/packages/kbn-dev-utils/src/proc_runner/observe_readable.ts new file mode 100644 index 0000000000000..8feab74d36321 --- /dev/null +++ b/packages/kbn-dev-utils/src/proc_runner/observe_readable.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 { Readable } from 'stream'; + +import * as Rx from 'rxjs'; +import { first, ignoreElements, mergeMap } from 'rxjs/operators'; + +/** + * Produces an Observable from a ReadableSteam that: + * - completes on the first "end" event + * - fails on the first "error" event + */ +export function observeReadable(readable: Readable): Rx.Observable { + return Rx.race( + Rx.fromEvent(readable, 'end').pipe( + first(), + ignoreElements() + ), + + Rx.fromEvent(readable, 'error').pipe( + first(), + mergeMap(err => Rx.throwError(err)) + ) + ); +} diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_signals.js b/packages/kbn-dev-utils/src/proc_runner/observe_signals.js deleted file mode 100644 index a4787a4f24fed..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/observe_signals.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. - */ - -import * as Rx from 'rxjs'; -import { mapTo } from 'rxjs/operators'; - -/** - * Creates an Observable from a Process object that: - * - emits "exit", "SIGINT", or "SIGTERM" events that occur - * - * @param {ReadableStream} readable - * @return {Rx.Observable} - */ -export function observeSignals(process) { - return Rx.merge( - Rx.fromEvent(process, 'exit').pipe(mapTo('exit')), - Rx.fromEvent(process, 'SIGINT').pipe(mapTo('SIGINT')), - Rx.fromEvent(process, 'SIGTERM').pipe(mapTo('SIGTERM')) - ); -} diff --git a/packages/kbn-dev-utils/src/proc_runner/proc.js b/packages/kbn-dev-utils/src/proc_runner/proc.js deleted file mode 100644 index 2fdba9b38ac63..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/proc.js +++ /dev/null @@ -1,160 +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 execa from 'execa'; -import { statSync } from 'fs'; - -import * as Rx from 'rxjs'; -import { tap, share, take, mergeMap, map, ignoreElements } from 'rxjs/operators'; -import { gray } from 'chalk'; - -import treeKill from 'tree-kill'; -import { promisify } from 'util'; -const treeKillAsync = promisify(treeKill); - -import { observeLines } from './observe_lines'; -import { createCliError } from './errors'; - -const SECOND = 1000; -const STOP_TIMEOUT = 30 * SECOND; - -async function withTimeout(attempt, ms, onTimeout) { - const TIMEOUT = Symbol('timeout'); - try { - await Promise.race([ - attempt(), - new Promise((resolve, reject) => setTimeout(() => reject(TIMEOUT), STOP_TIMEOUT)), - ]); - } catch (error) { - if (error === TIMEOUT) { - await onTimeout(); - } else { - throw error; - } - } -} - -export function createProc(name, { cmd, args, cwd, env, stdin, log }) { - log.info('[%s] > %s', name, cmd, args.join(' ')); - - // spawn fails with ENOENT when either the - // cmd or cwd don't exist, so we check for the cwd - // ahead of time so that the error is less ambiguous - try { - if (!statSync(cwd).isDirectory()) { - throw new Error(`cwd "${cwd}" exists but is not a directory`); - } - } catch (err) { - if (err.code === 'ENOENT') { - throw new Error(`cwd "${cwd}" does not exist`); - } - } - - const childProcess = execa(cmd, args, { - cwd, - env, - stdio: ['pipe', 'pipe', 'pipe'], - }); - - if (stdin) { - childProcess.stdin.end(stdin, 'utf8'); - } else { - childProcess.stdin.end(); - } - - return new (class Proc { - name = name; - - lines$ = Rx.merge(observeLines(childProcess.stdout), observeLines(childProcess.stderr)).pipe( - tap(line => log.write(` ${gray('proc')} [${gray(name)}] ${line}`)), - share() - ); - - outcome$ = Rx.defer(() => { - // observe first exit event - const exit$ = Rx.fromEvent(childProcess, 'exit').pipe( - take(1), - map(([code]) => { - if (this._stopCalled) { - return null; - } - // JVM exits with 143 on SIGTERM and 130 on SIGINT, dont' treat then as errors - if (code > 0 && !(code === 143 || code === 130)) { - throw createCliError(`[${name}] exited with code ${code}`); - } - - return code; - }) - ); - - // observe first error event until there is a close event - const error$ = Rx.fromEvent(childProcess, 'error').pipe( - take(1), - mergeMap(err => Rx.throwError(err)) - ); - - return Rx.race(exit$, error$); - }).pipe(share()); - - _outcomePromise = Rx.merge(this.lines$.pipe(ignoreElements()), this.outcome$).toPromise(); - - getOutcomePromise() { - return this._outcomePromise; - } - - _stopCalled = false; - - async stop(signal) { - if (this._stopCalled) { - return; - } - this._stopCalled = true; - await withTimeout( - async () => { - log.debug(`Sending "${signal}" to proc "${name}"`); - await treeKillAsync(childProcess.pid, signal); - await this.getOutcomePromise(); - }, - STOP_TIMEOUT, - async () => { - log.warning( - `Proc "${name}" was sent "${signal}" didn't emit the "exit" or "error" events after ${STOP_TIMEOUT} ms, sending SIGKILL` - ); - await treeKillAsync(childProcess.pid, 'SIGKILL'); - } - ); - - await withTimeout( - async () => { - try { - await this.getOutcomePromise(); - } catch (error) { - // ignore - } - }, - STOP_TIMEOUT, - async () => { - throw new Error( - `Proc "${name}" was stopped but never emitted either the "exit" or "error" event after ${STOP_TIMEOUT} ms` - ); - } - ); - } - })(); -} diff --git a/packages/kbn-dev-utils/src/proc_runner/proc.ts b/packages/kbn-dev-utils/src/proc_runner/proc.ts new file mode 100644 index 0000000000000..3b7d595e4b8cf --- /dev/null +++ b/packages/kbn-dev-utils/src/proc_runner/proc.ts @@ -0,0 +1,180 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import execa from 'execa'; +import { statSync } from 'fs'; + +import * as Rx from 'rxjs'; +import { tap, share, take, mergeMap, map, ignoreElements } from 'rxjs/operators'; +import chalk from 'chalk'; + +import treeKill from 'tree-kill'; +import { promisify } from 'util'; +const treeKillAsync = promisify(treeKill); + +import { ToolingLog } from '../tooling_log'; +import { observeLines } from './observe_lines'; +import { createCliError } from './errors'; + +const SECOND = 1000; +const STOP_TIMEOUT = 30 * SECOND; + +export interface ProcOptions { + cmd: string; + args: string[]; + cwd: string; + env?: Record; + stdin?: string; +} + +async function withTimeout( + attempt: () => Promise, + ms: number, + onTimeout: () => Promise +) { + const TIMEOUT = Symbol('timeout'); + try { + await Promise.race([ + attempt(), + new Promise((_, reject) => setTimeout(() => reject(TIMEOUT), ms)), + ]); + } catch (error) { + if (error === TIMEOUT) { + await onTimeout(); + } else { + throw error; + } + } +} + +export type Proc = ReturnType; + +export function startProc(name: string, options: ProcOptions, log: ToolingLog) { + const { cmd, args, cwd, env, stdin } = options; + + log.info('[%s] > %s', name, cmd, args.join(' ')); + + // spawn fails with ENOENT when either the + // cmd or cwd don't exist, so we check for the cwd + // ahead of time so that the error is less ambiguous + try { + if (!statSync(cwd).isDirectory()) { + throw new Error(`cwd "${cwd}" exists but is not a directory`); + } + } catch (err) { + if (err.code === 'ENOENT') { + throw new Error(`cwd "${cwd}" does not exist`); + } + } + + const childProcess = execa(cmd, args, { + cwd, + env, + stdio: ['pipe', 'pipe', 'pipe'], + }); + + if (stdin) { + childProcess.stdin.end(stdin, 'utf8'); + } else { + childProcess.stdin.end(); + } + + let stopCalled = false; + + const outcome$: Rx.Observable = Rx.race( + // observe first exit event + Rx.fromEvent(childProcess, 'exit').pipe( + take(1), + map(([code]: [number]) => { + if (stopCalled) { + return null; + } + // JVM exits with 143 on SIGTERM and 130 on SIGINT, dont' treat then as errors + if (code > 0 && !(code === 143 || code === 130)) { + throw createCliError(`[${name}] exited with code ${code}`); + } + + return code; + }) + ), + + // observe first error event + Rx.fromEvent(childProcess, 'error').pipe( + take(1), + mergeMap(err => Rx.throwError(err)) + ) + ).pipe(share()); + + const lines$ = Rx.merge( + observeLines(childProcess.stdout), + observeLines(childProcess.stderr) + ).pipe( + tap(line => log.write(` ${chalk.gray('proc')} [${chalk.gray(name)}] ${line}`)), + share() + ); + + const outcomePromise = Rx.merge(lines$.pipe(ignoreElements()), outcome$).toPromise(); + + async function stop(signal: NodeJS.Signals) { + if (stopCalled) { + return; + } + + stopCalled = true; + + await withTimeout( + async () => { + log.debug(`Sending "${signal}" to proc "${name}"`); + await treeKillAsync(childProcess.pid, signal); + await outcomePromise; + }, + STOP_TIMEOUT, + async () => { + log.warning( + `Proc "${name}" was sent "${signal}" didn't emit the "exit" or "error" events after ${STOP_TIMEOUT} ms, sending SIGKILL` + ); + await treeKillAsync(childProcess.pid, 'SIGKILL'); + } + ); + + await withTimeout( + async () => { + try { + await outcomePromise; + } catch (error) { + // ignore + } + }, + STOP_TIMEOUT, + async () => { + throw new Error( + `Proc "${name}" was stopped but never emitted either the "exit" or "error" event after ${STOP_TIMEOUT} ms` + ); + } + ); + } + + return { + name, + lines$, + outcome$, + outcomePromise, + stop, + }; +} diff --git a/packages/kbn-dev-utils/src/proc_runner/proc_runner.js b/packages/kbn-dev-utils/src/proc_runner/proc_runner.js deleted file mode 100644 index 8064195dfa935..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/proc_runner.js +++ /dev/null @@ -1,207 +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 moment from 'moment'; -import { filter, first, catchError } from 'rxjs/operators'; - -import { createCliError } from './errors'; -import { createProc } from './proc'; -import { observeSignals } from './observe_signals'; - -const noop = () => {}; - -/** - * Helper for starting and managing processes. In many ways it resembles the - * API from `grunt_run`, processes are named and can be started, waited for, - * backgrounded once they log something matching a RegExp... - * - * @class ProcRunner - */ -export class ProcRunner { - constructor(options) { - const { log } = options; - - this._closing = false; - this._procs = []; - this._log = log; - this._signalSubscription = observeSignals(process).subscribe({ - next: async signal => { - await this.teardown(signal); - if (signal !== 'exit') { - // resend the signal - process.kill(process.pid, signal); - } - }, - }); - } - - /** - * Start a process, tracking it by `name` - * @param {String} name - * @param {Object} options - * @property {String} options.cmd executable to run - * @property {Array?} options.args arguments to provide the executable - * @property {String?} options.cwd current working directory for the process - * @property {RegExp|Boolean} options.wait Should start() wait for some time? Use - * `true` will wait until the proc exits, - * a `RegExp` will wait until that log line - * is found - * @return {Promise} - */ - async run(name, options) { - const { - cmd, - args = [], - cwd = process.cwd(), - stdin = null, - wait = false, - env = process.env, - } = options; - - if (this._closing) { - throw new Error('ProcRunner is closing'); - } - - if (wait && !(wait instanceof RegExp) && wait !== true) { - throw new TypeError('wait param should either be a RegExp or `true`'); - } - - if (!!this._getProc(name)) { - throw new Error(`Process with name "${name}" already running`); - } - - const proc = this._createProc(name, { cmd, args, cwd, env, stdin }); - - try { - // wait for process to log matching line - if (wait instanceof RegExp) { - await proc.lines$ - .pipe( - filter(line => wait.test(line)), - first(), - catchError(err => { - if (err.name !== 'EmptyError') { - throw createCliError(`[${name}] exited without matching pattern: ${wait}`); - } else { - throw err; - } - }) - ) - .toPromise(); - } - - // wait for process to complete - if (wait === true) { - await proc.getOutcomePromise(); - } - } finally { - // while the procRunner closes promises will resolve/reject because - // processes and stopping, but consumers of run() shouldn't have to - // prepare for that, so just return a never-resolving promise - if (this._closing) { - await new Promise(noop); - } - } - } - - /** - * Stop a named proc - * @param {String} name - * @param {String} [signal='SIGTERM'] - * @return {Promise} - */ - async stop(name, signal = 'SIGTERM') { - const proc = this._getProc(name); - if (proc) { - await proc.stop(signal); - } else { - this._log.warning('[%s] already stopped', name); - } - } - - /** - * Wait for all running processes to stop naturally - * @return {Promise} - */ - async waitForAllToStop() { - await Promise.all(this._procs.map(proc => proc.getOutcomePromise())); - } - - /** - * Close the ProcRunner and stop all running - * processes with `signal` - * - * @param {String} [signal=undefined] - * @return {Promise} - */ - async teardown(signal) { - if (this._closing) return; - - this._closing = true; - this._signalSubscription.unsubscribe(); - this._signalSubscription = null; - - if (!signal && this._procs.length > 0) { - this._log.warning( - '%d processes left running, stop them with procs.stop(name):', - this._procs.length, - this._procs.map(proc => proc.name) - ); - } - - const stopWith = signal === 'exit' ? 'SIGKILL' : signal; - await Promise.all(this._procs.map(proc => proc.stop(stopWith))); - } - - _getProc(name) { - return this._procs.find(proc => proc.name === name); - } - - _createProc(name, options) { - const startMs = Date.now(); - const proc = createProc(name, { - ...options, - log: this._log, - }); - - this._procs.push(proc); - const remove = () => { - this._procs.splice(this._procs.indexOf(proc), 1); - }; - - // tie into proc outcome$, remove from _procs on compete - proc.outcome$.subscribe({ - next: code => { - const duration = moment.duration(Date.now() - startMs); - this._log.info('[%s] exited with %s after %s', name, code, duration.humanize()); - }, - complete: () => { - remove(); - }, - error: error => { - if (this._closing) { - this._log.error(error); - } - remove(); - }, - }); - - return proc; - } -} diff --git a/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts b/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts new file mode 100644 index 0000000000000..14c87766213cd --- /dev/null +++ b/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts @@ -0,0 +1,213 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import moment from 'moment'; +import { filter, first, catchError } from 'rxjs/operators'; +import exitHook from 'exit-hook'; + +import { ToolingLog } from '../tooling_log'; +import { createCliError } from './errors'; +import { Proc, ProcOptions, startProc } from './proc'; + +const noop = () => {}; + +interface RunOptions extends ProcOptions { + wait: true | RegExp; +} + +/** + * Helper for starting and managing processes. In many ways it resembles the + * API from `grunt_run`, processes are named and can be started, waited for, + * backgrounded once they log something matching a RegExp... + * + * @class ProcRunner + */ +export class ProcRunner { + private closing = false; + private procs: Proc[] = []; + private signalUnsubscribe: () => void; + + constructor(private log: ToolingLog) { + this.signalUnsubscribe = exitHook(() => { + this.teardown().catch(error => { + log.error(`ProcRunner teardown error: ${error.stack}`); + }); + }); + } + + /** + * Start a process, tracking it by `name` + * @param {String} name + * @param {Object} options + * @property {String} options.cmd executable to run + * @property {Array?} options.args arguments to provide the executable + * @property {String?} options.cwd current working directory for the process + * @property {RegExp|Boolean} options.wait Should start() wait for some time? Use + * `true` will wait until the proc exits, + * a `RegExp` will wait until that log line + * is found + * @return {Promise} + */ + async run(name: string, options: RunOptions) { + const { + cmd, + args = [], + cwd = process.cwd(), + stdin = undefined, + wait = false, + env = process.env, + } = options; + + if (this.closing) { + throw new Error('ProcRunner is closing'); + } + + if (wait && !(wait instanceof RegExp) && wait !== true) { + throw new TypeError('wait param should either be a RegExp or `true`'); + } + + if (!!this.getProc(name)) { + throw new Error(`Process with name "${name}" already running`); + } + + const proc = this.startProc(name, { + cmd, + args, + cwd, + env, + stdin, + }); + + try { + if (wait instanceof RegExp) { + // wait for process to log matching line + await proc.lines$ + .pipe( + filter(line => wait.test(line)), + first(), + catchError(err => { + if (err.name !== 'EmptyError') { + throw createCliError(`[${name}] exited without matching pattern: ${wait}`); + } else { + throw err; + } + }) + ) + .toPromise(); + } + + if (wait === true) { + // wait for process to complete + await proc.outcomePromise; + } + } finally { + // while the procRunner closes promises will resolve/reject because + // processes and stopping, but consumers of run() shouldn't have to + // prepare for that, so just return a never-resolving promise + if (this.closing) { + await new Promise(noop); + } + } + } + + /** + * Stop a named proc + */ + async stop(name: string, signal: NodeJS.Signals = 'SIGTERM') { + const proc = this.getProc(name); + if (proc) { + await proc.stop(signal); + } else { + this.log.warning('[%s] already stopped', name); + } + } + + /** + * Wait for all running processes to stop naturally + * @return {Promise} + */ + async waitForAllToStop() { + await Promise.all(this.procs.map(proc => proc.outcomePromise)); + } + + /** + * Close the ProcRunner and stop all running + * processes with `signal` + * + * @param {String} [signal=undefined] + * @return {Promise} + */ + async teardown(signal: NodeJS.Signals | 'exit' = 'exit') { + if (this.closing) { + return; + } + + this.closing = true; + this.signalUnsubscribe(); + + if (!signal && this.procs.length > 0) { + this.log.warning( + '%d processes left running, stop them with procs.stop(name):', + this.procs.length, + this.procs.map(proc => proc.name) + ); + } + + await Promise.all( + this.procs.map(async proc => { + await proc.stop(signal === 'exit' ? 'SIGKILL' : signal); + }) + ); + } + + private getProc(name: string) { + return this.procs.find(proc => { + return proc.name === name; + }); + } + + private startProc(name: string, options: ProcOptions) { + const startMs = Date.now(); + const proc = startProc(name, options, this.log); + + this.procs.push(proc); + const remove = () => { + this.procs.splice(this.procs.indexOf(proc), 1); + }; + + // tie into proc outcome$, remove from _procs on compete + proc.outcome$.subscribe({ + next: code => { + const duration = moment.duration(Date.now() - startMs); + this.log.info('[%s] exited with %s after %s', name, code, duration.humanize()); + }, + complete: () => { + remove(); + }, + error: error => { + if (this.closing) { + this.log.error(error); + } + remove(); + }, + }); + + return proc; + } +} diff --git a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.js b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.js deleted file mode 100644 index 21994d8ec8360..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.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. - */ - -import { ProcRunner } from './proc_runner'; - -/** - * Create a ProcRunner and pass it to an async function. When - * the async function finishes the ProcRunner is torn-down - * automatically - * - * @param {ToolingLog} log - * @param {async Function} fn - * @return {Promise} - */ -export async function withProcRunner(log, fn) { - const procs = new ProcRunner({ log }); - try { - await fn(procs); - } finally { - await procs.teardown(); - } -} diff --git a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.js b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.js deleted file mode 100644 index 4d0329de7c32a..0000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.js +++ /dev/null @@ -1,79 +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 { ToolingLog } from '../tooling_log'; -import { withProcRunner } from './with_proc_runner'; -import { ProcRunner } from './proc_runner'; - -it('passes proc runner to a function', async () => { - await withProcRunner(new ToolingLog(), proc => { - expect(proc).toBeInstanceOf(ProcRunner); - }); -}); - -it('calls procRunner.teardown() if function returns synchronously', async () => { - let teardownSpy; - await withProcRunner(new ToolingLog(), proc => { - teardownSpy = jest.spyOn(proc, 'teardown'); - }); - - expect(teardownSpy).toHaveBeenCalled(); -}); - -it('calls procRunner.teardown() if function throw synchronous error, and rejects with the error', async () => { - const error = new Error('foo'); - let teardownSpy; - - await expect( - withProcRunner(new ToolingLog(), proc => { - teardownSpy = jest.spyOn(proc, 'teardown'); - throw error; - }) - ).rejects.toThrowError(error); - - expect(teardownSpy).toHaveBeenCalled(); -}); - -it('waits for promise to resolve before tearing down proc', async () => { - let teardownSpy; - - await withProcRunner(new ToolingLog(), async proc => { - await new Promise(resolve => setTimeout(resolve, 500)); - teardownSpy = jest.spyOn(proc, 'teardown'); - }); - - expect(teardownSpy).not.toBe(undefined); - expect(teardownSpy).toHaveBeenCalled(); -}); - -it('waits for promise to reject before tearing down proc and rejecting with the error', async () => { - const error = new Error('foo'); - let teardownSpy; - - await expect( - withProcRunner(new ToolingLog(), async proc => { - await new Promise(resolve => setTimeout(resolve, 500)); - teardownSpy = jest.spyOn(proc, 'teardown'); - throw error; - }) - ).rejects.toThrowError(error); - - expect(teardownSpy).not.toBe(undefined); - expect(teardownSpy).toHaveBeenCalled(); -}); diff --git a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.ts b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.test.ts new file mode 100644 index 0000000000000..e37bdcc40ca1c --- /dev/null +++ b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.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 { ToolingLog } from '../tooling_log'; +import { withProcRunner } from './with_proc_runner'; +import { ProcRunner } from './proc_runner'; + +it('passes proc runner to a function', async () => { + await withProcRunner(new ToolingLog(), async proc => { + expect(proc).toBeInstanceOf(ProcRunner); + }); +}); + +it('calls procRunner.teardown() if function returns synchronously', async () => { + let teardownSpy; + await withProcRunner(new ToolingLog(), async proc => { + teardownSpy = jest.spyOn(proc, 'teardown'); + }); + + expect(teardownSpy).toHaveBeenCalled(); +}); + +it('calls procRunner.teardown() if function throw synchronous error, and rejects with the error', async () => { + const error = new Error('foo'); + let teardownSpy; + + await expect( + withProcRunner(new ToolingLog(), async proc => { + teardownSpy = jest.spyOn(proc, 'teardown'); + throw error; + }) + ).rejects.toThrowError(error); + + expect(teardownSpy).toHaveBeenCalled(); +}); + +it('waits for promise to resolve before tearing down proc', async () => { + let teardownSpy; + + await withProcRunner(new ToolingLog(), async proc => { + await new Promise(resolve => setTimeout(resolve, 500)); + teardownSpy = jest.spyOn(proc, 'teardown'); + }); + + expect(teardownSpy).not.toBe(undefined); + expect(teardownSpy).toHaveBeenCalled(); +}); + +it('waits for promise to reject before tearing down proc and rejecting with the error', async () => { + const error = new Error('foo'); + let teardownSpy; + + await expect( + withProcRunner(new ToolingLog(), async proc => { + await new Promise(resolve => setTimeout(resolve, 500)); + teardownSpy = jest.spyOn(proc, 'teardown'); + throw error; + }) + ).rejects.toThrowError(error); + + expect(teardownSpy).not.toBe(undefined); + expect(teardownSpy).toHaveBeenCalled(); +}); diff --git a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.ts b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.ts new file mode 100644 index 0000000000000..85fc74f9124ec --- /dev/null +++ b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.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. + */ + +import { ProcRunner } from './proc_runner'; +import { ToolingLog } from '../tooling_log'; + +/** + * Create a ProcRunner and pass it to an async function. When + * the async function finishes the ProcRunner is torn-down + * automatically + * + * @param {ToolingLog} log + * @param {async Function} fn + * @return {Promise} + */ +export async function withProcRunner( + log: ToolingLog, + fn: (procs: ProcRunner) => Promise +): Promise { + const procs = new ProcRunner(log); + + try { + await fn(procs); + } finally { + await procs.teardown(); + } +} diff --git a/packages/kbn-dev-utils/src/run/README.md b/packages/kbn-dev-utils/src/run/README.md new file mode 100644 index 0000000000000..913b601058f87 --- /dev/null +++ b/packages/kbn-dev-utils/src/run/README.md @@ -0,0 +1,133 @@ +# @kbn/dev-utils > run() + +Helper functions for writing little scripts for random build/ci/dev tasks. + +## Usage + +Define the function that should validate the CLI arguments and call your task fn: + +```ts +// dev/my_task/run_my_task.ts +import { createFlagError, run } from '@kbn/dev-utils'; + +run( + async ({ flags, log }) => { + if (typeof flags.path !== 'string') { + throw createFlagError('please provide a single --path flag'); + } + + await runTask(flags.path); + log.success('task complete'); + }, + { + description: ` + Run my special task + `, + flags: { + string: ['path'], + help: ` + --path Required, path to the file to operate on + ` + }, + } +); +``` + +Define the script which will setup node and load the script source: + +```js +// scripts/my_task.js + +require('../src/setup_node_env'); +require('../src/dev/my_task/run_my_task'); +``` + +Try out the script: + +```sh +$ node scripts/my_task + +# ERROR please provide a single --path flag +# +# node scripts/my_task.js +# +# Run my special task +# +# Options: +# --path Required, path to the file to operate on +# --verbose, -v Log verbosely +# --debug Log debug messages (less than verbose) +# --quiet Only log errors +# --silent Don't log anything +# --help Show this message +# +``` + +## API + +- ***`run(fn: async ({ flags: Flags, log: ToolingLog, addCleanupTask }) => Promise, options: Options)`*** + + Execte an async function, passing it the parsed flags and a tooling log that is configured to the requested logging level. If the returned promise is rejected with an error created by `createFailError(...)` or `createFlagError(...)` the process will exit as described by the error, otherwise the process will exit with code 1. + + **`fn` Params:** + - *[`log: ToolingLog`](../../../packages/kbn-dev-utils/src/tooling_log/tooling_log.js)*: + + An instance of the `ToolingLog` that is configured with the standard flags: `--verbose`, `--quiet`, `--silent`, and `--debug` + + - *[`flags: Flags`](flags.ts)*: + + The parsed CLI flags, created by [`getopts`](https://www.npmjs.com/package/getopts). Includes the default flags for controlling the log level of the ToolingLog, and `flags.unexpected`, which is an array of flag names which were passed but not expected. + + - *`addCleanupTask: (task: CleanupTask) => void`*: + + A function that registers a task to be called __once__ as soon as one of the following occurs: + + 1. `fn` resolve/rejects + 2. something calls `process.exit()` + 3. the user hits ctrl+c in their terminal causing the SIGINT signal to be sent to the process + + **`Options`:** + - *`usage: string`* + + A bit of text to replace the default usage in the `--help` text. + + - *`description: string`* + + A bit of text to replace the default description in the `--help` text. + + - *`flags.help: string`* + + A bit of text included at the top of the `Options:` section of the `--help` text. + + - *`flags.string: string[]`* + + An array of flag names that are expected to have a string value. + + - *`flags.boolean: string[]`* + + An array of flag names that are expected to have a boolean value. + + - *`flags.alias: { [short: string], string }`* + + A map of short flag names to long flag names, used to expand short flags like `-v` to `--verbose`. + + - *`flags.default: { [name: string]: string | string[] | boolean | undefined }`* + + A map of flag names to their default value. If the flag is not defined this value will be set in the flags object passed to the run `fn`. + + - *`flags.allowUnexpected: boolean`* + + By default, any flag that is passed but not mentioned in `flags.string`, `flags.boolean`, `flags.alias` or `flags.default` will trigger an error, preventing the run function from calling its first argument. If you have a reason to disable this behavior set this option to `true`. + + +- ***`createFailError(reason: string, options: { exitCode: number, showHelp: boolean }): FailError`*** + + Create and return an error object that, when thrown within `run(...)` can customize the failure behavior of the CLI. `reason` is printed instead of a stacktrace, `options.exitCode` customizes the exit code of the process, and `options.showHelp` will print the help text before exiting. + +- ***`createFlagError(reason: string)`*** + + Shortcut for calling `createFailError()` with `options.showHelp`, as errors caused by invalid flags should print the help message to help users debug their usage. + +- ***`isFailError(error: any)`*** + + Determine if a value is an error created by `createFailError(...)`. \ No newline at end of file diff --git a/src/dev/run/fail.ts b/packages/kbn-dev-utils/src/run/fail.ts similarity index 100% rename from src/dev/run/fail.ts rename to packages/kbn-dev-utils/src/run/fail.ts diff --git a/src/dev/run/flags.ts b/packages/kbn-dev-utils/src/run/flags.ts similarity index 100% rename from src/dev/run/flags.ts rename to packages/kbn-dev-utils/src/run/flags.ts diff --git a/packages/kbn-dev-utils/src/run/index.ts b/packages/kbn-dev-utils/src/run/index.ts new file mode 100644 index 0000000000000..5e1a42deefffb --- /dev/null +++ b/packages/kbn-dev-utils/src/run/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 { run } from './run'; +export { Flags } from './flags'; +export { createFailError, createFlagError, combineErrors, isFailError } from './fail'; diff --git a/src/dev/run/run.ts b/packages/kbn-dev-utils/src/run/run.ts similarity index 97% rename from src/dev/run/run.ts rename to packages/kbn-dev-utils/src/run/run.ts index 6eb1bd973519e..06746c663b917 100644 --- a/src/dev/run/run.ts +++ b/packages/kbn-dev-utils/src/run/run.ts @@ -20,7 +20,7 @@ // @ts-ignore @types are outdated and module is super simple import exitHook from 'exit-hook'; -import { pickLevelFromFlags, ToolingLog } from '@kbn/dev-utils'; +import { pickLevelFromFlags, ToolingLog } from '../tooling_log'; import { createFlagError, isFailError } from './fail'; import { Flags, getFlags, getHelp } from './flags'; diff --git a/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.d.ts b/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.d.ts deleted file mode 100644 index 66e94571a2300..0000000000000 --- a/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.d.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. - */ - -export function createAbsolutePathSerializer( - rootPath: string -): { print(...args: any[]): string; test(value: any): boolean }; diff --git a/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.js b/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.js deleted file mode 100644 index d944772048eb9..0000000000000 --- a/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.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. - */ - -export function createAbsolutePathSerializer(rootPath) { - return { - print: value => value.replace(rootPath, '').replace(/\\/g, '/'), - test: value => typeof value === 'string' && value.startsWith(rootPath), - }; -} diff --git a/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.ts b/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.ts new file mode 100644 index 0000000000000..661ed7329347f --- /dev/null +++ b/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.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 function createAbsolutePathSerializer(rootPath: string) { + return { + print: (value: string) => value.replace(rootPath, '').replace(/\\/g, '/'), + test: (value: any) => typeof value === 'string' && value.startsWith(rootPath), + }; +} diff --git a/packages/kbn-dev-utils/src/serializers/index.js b/packages/kbn-dev-utils/src/serializers/index.js deleted file mode 100644 index 3b49e243058df..0000000000000 --- a/packages/kbn-dev-utils/src/serializers/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 { createAbsolutePathSerializer } from './absolute_path_serializer'; diff --git a/packages/kbn-dev-utils/src/serializers/index.d.ts b/packages/kbn-dev-utils/src/serializers/index.ts similarity index 100% rename from packages/kbn-dev-utils/src/serializers/index.d.ts rename to packages/kbn-dev-utils/src/serializers/index.ts diff --git a/packages/kbn-dev-utils/src/streams/concat_stream.js b/packages/kbn-dev-utils/src/streams/concat_stream.js deleted file mode 100644 index e3f8f7261d2b7..0000000000000 --- a/packages/kbn-dev-utils/src/streams/concat_stream.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 { createReduceStream } from './reduce_stream'; - -/** - * Creates a Transform stream that consumes all provided - * values and concatenates them using each values `concat` - * method. - * - * Concatenate strings: - * createListStream(['f', 'o', 'o']) - * .pipe(createConcatStream()) - * .on('data', console.log) - * // logs "foo" - * - * Concatenate values into an array: - * createListStream([1,2,3]) - * .pipe(createConcatStream([])) - * .on('data', console.log) - * // logs "[1,2,3]" - * - * - * @param {any} initial The initial value that subsequent - * items will concat with - * @return {Transform} - */ -export function createConcatStream(initial) { - return createReduceStream((acc, chunk) => acc.concat(chunk), initial); -} diff --git a/packages/kbn-dev-utils/src/streams/index.js b/packages/kbn-dev-utils/src/streams/index.js deleted file mode 100644 index 18fda5995090f..0000000000000 --- a/packages/kbn-dev-utils/src/streams/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 { createConcatStream } from './concat_stream'; -export { createPromiseFromStreams } from './promise_from_streams'; diff --git a/packages/kbn-dev-utils/src/streams/promise_from_streams.js b/packages/kbn-dev-utils/src/streams/promise_from_streams.js deleted file mode 100644 index 6cd88cb76c648..0000000000000 --- a/packages/kbn-dev-utils/src/streams/promise_from_streams.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. - */ - -/** - * Take an array of streams, pipe the output - * from each one into the next, listening for - * errors from any of the streams, and then resolve - * the promise once the final stream has finished - * writing/reading. - * - * If the last stream is readable, it's final value - * will be provided as the promise value. - * - * Errors emitted from any stream will cause - * the promise to be rejected with that error. - * - * @param {Array} streams - * @return {Promise} - */ -export async function createPromiseFromStreams(streams) { - const last = streams[streams.length - 1]; - - // reject if any of the streams emits an error - const anyStreamFailure = new Promise((resolve, reject) => { - streams.forEach((stream, i) => { - if (i > 0) streams[i - 1].pipe(stream); - stream.on('error', reject); - return stream; - }); - }); - - // resolve when the last stream has finished writing, or - // immediately if the last stream is not writable - const lastFinishedWriting = new Promise(resolve => { - if (typeof last.write !== 'function') { - resolve(); - return; - } - - last.on('finish', resolve); - }); - - // resolve with the final value provided by the last stream - // after the last stream has provided it, or immediately if the - // stream is not readable - const lastFinishedReading = new Promise(resolve => { - if (typeof last.read !== 'function') { - resolve(); - return; - } - - let finalChunk; - last.on('data', chunk => { - finalChunk = chunk; - }); - last.on('end', () => { - resolve(finalChunk); - }); - }); - - // wait (and rethrow) the first error, or for the last stream - // to both finish writing and providing values to read - await Promise.race([anyStreamFailure, Promise.all([lastFinishedWriting, lastFinishedReading])]); - - // return the final chunk read from the last stream - return await lastFinishedReading; -} diff --git a/packages/kbn-dev-utils/src/streams/reduce_stream.js b/packages/kbn-dev-utils/src/streams/reduce_stream.js deleted file mode 100644 index d66b0124d1dab..0000000000000 --- a/packages/kbn-dev-utils/src/streams/reduce_stream.js +++ /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 { Transform } from 'stream'; - -/** - * Create a transform stream that consumes each chunk it receives - * and passes it to the reducer, which will return the new value - * for the stream. Once all chunks have been received the reduce - * stream provides the result of final call to the reducer to - * subscribers. - * - * @param {Function} - * @param {any} initial Initial value for the stream, if undefined - * then the first chunk provided is used as the - * initial value. - * @return {Transform} - */ -export function createReduceStream(reducer, initial) { - let i = -1; - let value = initial; - - // if the reducer throws an error then the value is - // considered invalid and the stream will never provide - // it to subscribers. We will also stop calling the - // reducer for any new data that is provided to us - let failed = false; - - if (typeof reducer !== 'function') { - throw new TypeError('reducer must be a function'); - } - - return new Transform({ - readableObjectMode: true, - writableObjectMode: true, - async transform(chunk, enc, callback) { - try { - if (failed) { - return callback(); - } - - i += 1; - if (i === 0 && initial === undefined) { - value = chunk; - } else { - value = await reducer(value, chunk, enc); - } - - callback(); - } catch (err) { - failed = true; - callback(err); - } - }, - - flush(callback) { - if (!failed) { - this.push(value); - } - - callback(); - }, - }); -} diff --git a/packages/kbn-dev-utils/src/tooling_log/__snapshots__/log_levels.test.js.snap b/packages/kbn-dev-utils/src/tooling_log/__snapshots__/log_levels.test.ts.snap similarity index 100% rename from packages/kbn-dev-utils/src/tooling_log/__snapshots__/log_levels.test.js.snap rename to packages/kbn-dev-utils/src/tooling_log/__snapshots__/log_levels.test.ts.snap diff --git a/packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log.test.js.snap b/packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log.test.ts.snap similarity index 100% rename from packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log.test.js.snap rename to packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log.test.ts.snap diff --git a/packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log_text_writer.test.js.snap b/packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log_text_writer.test.ts.snap similarity index 100% rename from packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log_text_writer.test.js.snap rename to packages/kbn-dev-utils/src/tooling_log/__snapshots__/tooling_log_text_writer.test.ts.snap diff --git a/packages/kbn-dev-utils/src/tooling_log/index.d.ts b/packages/kbn-dev-utils/src/tooling_log/index.d.ts deleted file mode 100644 index 88efd6cf913bb..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/index.d.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. - */ - -export { ToolingLog } from './tooling_log'; -export { ToolingLogTextWriter, WriterConfig } from './tooling_log_text_writer'; -export { pickLevelFromFlags, LogLevel } from './log_levels'; diff --git a/packages/kbn-dev-utils/src/tooling_log/index.js b/packages/kbn-dev-utils/src/tooling_log/index.js deleted file mode 100644 index bd394c9a1315a..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/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 { ToolingLog } from './tooling_log'; -export { ToolingLogTextWriter } from './tooling_log_text_writer'; -export { pickLevelFromFlags } from './log_levels'; diff --git a/packages/kbn-dev-utils/src/tooling_log/index.ts b/packages/kbn-dev-utils/src/tooling_log/index.ts new file mode 100644 index 0000000000000..e00e1c8b7d1b9 --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/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 { ToolingLog } from './tooling_log'; +export { ToolingLogTextWriter, ToolingLogTextWriterConfig } from './tooling_log_text_writer'; +export { pickLevelFromFlags, LogLevel } from './log_levels'; diff --git a/packages/kbn-dev-utils/src/tooling_log/log_levels.d.ts b/packages/kbn-dev-utils/src/tooling_log/log_levels.d.ts deleted file mode 100644 index 442610ca88d78..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/log_levels.d.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. - */ - -export type LogLevel = 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose'; - -export interface ParsedLogLevel { - name: LogLevel; - flags: { [key in LogLevel]: boolean }; -} - -export function pickLevelFromFlags( - flags: { [key: string]: any }, - options?: { default?: LogLevel } -): LogLevel; - -export function parseLogLevel(level: LogLevel): ParsedLogLevel; diff --git a/packages/kbn-dev-utils/src/tooling_log/log_levels.js b/packages/kbn-dev-utils/src/tooling_log/log_levels.js deleted file mode 100644 index 67b123b299071..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/log_levels.js +++ /dev/null @@ -1,44 +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 LEVELS = ['silent', 'error', 'warning', 'info', 'debug', 'verbose']; - -export function pickLevelFromFlags(flags, options = {}) { - if (flags.verbose) return 'verbose'; - if (flags.debug) return 'debug'; - if (flags.quiet) return 'error'; - if (flags.silent) return 'silent'; - return options.default || 'info'; -} - -export function parseLogLevel(name) { - const i = LEVELS.indexOf(name); - - if (i === -1) { - const msg = `Invalid log level "${name}" ` + `(expected one of ${LEVELS.join(',')})`; - throw new Error(msg); - } - - const flags = {}; - LEVELS.forEach((level, levelI) => { - flags[level] = levelI <= i; - }); - - return { name, flags }; -} diff --git a/packages/kbn-dev-utils/src/tooling_log/log_levels.test.js b/packages/kbn-dev-utils/src/tooling_log/log_levels.test.js deleted file mode 100644 index eecc33cc90696..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/log_levels.test.js +++ /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 { parseLogLevel } from './log_levels'; - -it('parses valid log levels correctly', () => { - expect(parseLogLevel('silent')).toMatchSnapshot('silent'); - expect(parseLogLevel('error')).toMatchSnapshot('error'); - expect(parseLogLevel('warning')).toMatchSnapshot('warning'); - expect(parseLogLevel('info')).toMatchSnapshot('info'); - expect(parseLogLevel('debug')).toMatchSnapshot('debug'); - expect(parseLogLevel('verbose')).toMatchSnapshot('verbose'); -}); - -it('throws error for invalid levels', () => { - expect(() => parseLogLevel('warn')).toThrowErrorMatchingSnapshot('warn'); - expect(() => parseLogLevel('foo')).toThrowErrorMatchingSnapshot('foo'); - expect(() => parseLogLevel('bar')).toThrowErrorMatchingSnapshot('bar'); -}); diff --git a/packages/kbn-dev-utils/src/tooling_log/log_levels.test.ts b/packages/kbn-dev-utils/src/tooling_log/log_levels.test.ts new file mode 100644 index 0000000000000..ae73bc9a93047 --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/log_levels.test.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 { parseLogLevel } from './log_levels'; + +it('parses valid log levels correctly', () => { + expect(parseLogLevel('silent')).toMatchSnapshot('silent'); + expect(parseLogLevel('error')).toMatchSnapshot('error'); + expect(parseLogLevel('warning')).toMatchSnapshot('warning'); + expect(parseLogLevel('info')).toMatchSnapshot('info'); + expect(parseLogLevel('debug')).toMatchSnapshot('debug'); + expect(parseLogLevel('verbose')).toMatchSnapshot('verbose'); +}); + +it('throws error for invalid levels', () => { + // @ts-ignore + expect(() => parseLogLevel('warn')).toThrowErrorMatchingSnapshot('warn'); + // @ts-ignore + expect(() => parseLogLevel('foo')).toThrowErrorMatchingSnapshot('foo'); + // @ts-ignore + expect(() => parseLogLevel('bar')).toThrowErrorMatchingSnapshot('bar'); +}); diff --git a/packages/kbn-dev-utils/src/tooling_log/log_levels.ts b/packages/kbn-dev-utils/src/tooling_log/log_levels.ts new file mode 100644 index 0000000000000..9e7d7ffe45134 --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/log_levels.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. + */ + +export type LogLevel = 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose'; +const LEVELS: LogLevel[] = ['silent', 'error', 'warning', 'info', 'debug', 'verbose']; + +export function pickLevelFromFlags( + flags: Record, + options: { default?: LogLevel } = {} +) { + if (flags.verbose) return 'verbose'; + if (flags.debug) return 'debug'; + if (flags.quiet) return 'error'; + if (flags.silent) return 'silent'; + return options.default || 'info'; +} + +export type ParsedLogLevel = ReturnType; + +export function parseLogLevel(name: LogLevel) { + const i = LEVELS.indexOf(name); + + if (i === -1) { + const msg = `Invalid log level "${name}" ` + `(expected one of ${LEVELS.join(',')})`; + throw new Error(msg); + } + + const flags: { [key: string]: boolean } = {}; + LEVELS.forEach((level, levelI) => { + flags[level] = levelI <= i; + }); + + return { + name, + flags: flags as { [key in LogLevel]: boolean }, + }; +} diff --git a/packages/kbn-dev-utils/src/tooling_log/message.ts b/packages/kbn-dev-utils/src/tooling_log/message.ts new file mode 100644 index 0000000000000..e47bd82be53a6 --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/message.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export type MessageTypes = 'verbose' | 'debug' | 'info' | 'success' | 'warning' | 'error' | 'write'; + +export interface Message { + type: MessageTypes; + indent: number; + args: any[]; +} diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.d.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log.d.ts deleted file mode 100644 index 2b4b86f3b1f76..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log.d.ts +++ /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. - */ - -// eslint-disable max-classes-per-file - -import * as Rx from 'rxjs'; - -import { ToolingLogWriter, WriterConfig } from './tooling_log_text_writer'; - -export interface LogMessage { - type: 'verbose' | 'debug' | 'info' | 'success' | 'warning' | 'error' | 'write'; - indent: number; - args: any[]; -} - -export class ToolingLog { - constructor(config?: WriterConfig); - public verbose(...args: any[]): void; - public debug(...args: any[]): void; - public info(...args: any[]): void; - public success(...args: any[]): void; - public warning(...args: any[]): void; - public error(errOrMsg: string | Error): void; - public write(...args: any[]): void; - public indent(spaces?: number): void; - public getWriters(): ToolingLogWriter[]; - public setWriters(reporters: ToolingLogWriter[]): void; - public getWritten$(): Rx.Observable; -} diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.js b/packages/kbn-dev-utils/src/tooling_log/tooling_log.js deleted file mode 100644 index 1b309ac28fc3f..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log.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 * as Rx from 'rxjs'; -import { EventEmitter } from 'events'; - -import { ToolingLogTextWriter } from './tooling_log_text_writer'; - -export class ToolingLog extends EventEmitter { - /** - * Create a ToolingLog object - * @param {WriterConfig} writerConfig - */ - constructor(writerConfig) { - super(); - - this._indent = 0; - this._writers = writerConfig ? [new ToolingLogTextWriter(writerConfig)] : []; - this._written$ = new Rx.Subject(); - } - - indent(delta = 0) { - this._indent = Math.max(this._indent + delta, 0); - return this._indent; - } - - verbose(...args) { - this._write('verbose', args); - } - - debug(...args) { - this._write('debug', args); - } - - info(...args) { - this._write('info', args); - } - - success(...args) { - this._write('success', args); - } - - warning(...args) { - this._write('warning', args); - } - - error(error) { - this._write('error', [error]); - } - - write(...args) { - this._write('write', args); - } - - getWriters() { - return this._writers.slice(0); - } - - setWriters(writers) { - this._writers = [...writers]; - } - - getWritten$() { - return this._written$.asObservable(); - } - - _write(type, args) { - const msg = { - type, - indent: this._indent, - args, - }; - - let written = false; - for (const writer of this._writers) { - if (writer.write(msg)) { - written = true; - } - } - - if (written) { - this._written$.next(msg); - } - } -} diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.js b/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.js deleted file mode 100644 index fb1095caeefa0..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.js +++ /dev/null @@ -1,143 +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 { toArray, takeUntil } from 'rxjs/operators'; - -import { ToolingLog } from './tooling_log'; -import { ToolingLogTextWriter } from './tooling_log_text_writer'; - -it('creates zero writers without a config', () => { - const log = new ToolingLog(); - expect(log.getWriters()).toHaveLength(0); -}); - -it('creates a single writer with a single object', () => { - const log = new ToolingLog({ level: 'warning', writeTo: process.stdout }); - expect(log.getWriters()).toHaveLength(1); - const [writer] = log.getWriters(); - expect(writer.level).toHaveProperty('name', 'warning'); - expect(writer.writeTo).toBe(process.stdout); -}); - -describe('#get/setWriters()', () => { - it('returns/replaces the current writers', () => { - const log = new ToolingLog(); - expect(log.getWriters()).toHaveLength(0); - - log.setWriters([ - new ToolingLogTextWriter({ - level: 'verbose', - writeTo: process.stdout, - }), - new ToolingLogTextWriter({ - level: 'verbose', - writeTo: process.stdout, - }), - ]); - expect(log.getWriters()).toHaveLength(2); - - log.setWriters([]); - expect(log.getWriters()).toHaveLength(0); - }); -}); - -describe('#indent()', () => { - it('changes the indent on each written msg', () => { - const log = new ToolingLog(); - const write = jest.fn(); - log.setWriters([{ write }]); - - log.indent(1); - log.debug('foo'); - log.indent(2); - log.debug('bar'); - log.indent(3); - log.debug('baz'); - log.indent(-2); - log.debug('box'); - log.indent(-Infinity); - log.debug('foo'); - - expect(write.mock.calls).toMatchSnapshot(); - }); -}); - -['verbose', 'debug', 'info', 'success', 'warning', 'error', 'write'].forEach(method => { - describe(`#${method}()`, () => { - it(`sends a msg of type "${method}" to each writer with indent and arguments`, () => { - const log = new ToolingLog(); - const writeA = jest.fn(); - const writeB = jest.fn(); - - log.setWriters([{ write: writeA }, { write: writeB }]); - - if (method === 'error') { - const error = new Error('error message'); - error.stack = '... stack trace ...'; - log.error(error); - log.error('string message'); - } else { - log[method]('foo', 'bar', 'baz'); - } - - expect(writeA.mock.calls).toMatchSnapshot(); - expect(writeA.mock.calls).toEqual(writeB.mock.calls); - }); - }); -}); - -describe('#getWritten$()', () => { - async function testWrittenMsgs(writers) { - const log = new ToolingLog(); - log.setWriters(writers); - - const done$ = new Rx.Subject(); - const promise = log - .getWritten$() - .pipe( - takeUntil(done$), - toArray() - ) - .toPromise(); - - log.debug('foo'); - log.info('bar'); - log.verbose('baz'); - done$.next(); - - expect(await promise).toMatchSnapshot(); - } - - it('does not emit msg when no writers', async () => { - await testWrittenMsgs([]); - }); - - it('emits msg if all writers return true', async () => { - await testWrittenMsgs([{ write: jest.fn(() => true) }, { write: jest.fn(() => true) }]); - }); - - it('emits msg if some writers return true', async () => { - await testWrittenMsgs([{ write: jest.fn(() => true) }, { write: jest.fn(() => false) }]); - }); - - it('does not emit msg if all writers return false', async () => { - await testWrittenMsgs([{ write: jest.fn(() => false) }, { write: jest.fn(() => false) }]); - }); -}); diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.ts new file mode 100644 index 0000000000000..259bfd782d3fb --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log.test.ts @@ -0,0 +1,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. + */ + +import * as Rx from 'rxjs'; +import { toArray, takeUntil } from 'rxjs/operators'; + +import { ToolingLog } from './tooling_log'; +import { Writer } from './writer'; +import { ToolingLogTextWriter } from './tooling_log_text_writer'; + +it('creates zero writers without a config', () => { + const log = new ToolingLog(); + expect(log.getWriters()).toHaveLength(0); +}); + +it('creates a single writer with a single object', () => { + const log = new ToolingLog({ level: 'warning', writeTo: process.stdout }); + expect(log.getWriters()).toHaveLength(1); + const [writer] = log.getWriters() as [ToolingLogTextWriter]; + expect(writer.level).toHaveProperty('name', 'warning'); + expect(writer.writeTo).toBe(process.stdout); +}); + +describe('#get/setWriters()', () => { + it('returns/replaces the current writers', () => { + const log = new ToolingLog(); + expect(log.getWriters()).toHaveLength(0); + + log.setWriters([ + new ToolingLogTextWriter({ + level: 'verbose', + writeTo: process.stdout, + }), + new ToolingLogTextWriter({ + level: 'verbose', + writeTo: process.stdout, + }), + ]); + expect(log.getWriters()).toHaveLength(2); + + log.setWriters([]); + expect(log.getWriters()).toHaveLength(0); + }); +}); + +describe('#indent()', () => { + it('changes the indent on each written msg', () => { + const log = new ToolingLog(); + const write = jest.fn(); + log.setWriters([{ write }]); + + log.indent(1); + log.debug('foo'); + log.indent(2); + log.debug('bar'); + log.indent(3); + log.debug('baz'); + log.indent(-2); + log.debug('box'); + log.indent(-Infinity); + log.debug('foo'); + + expect(write.mock.calls).toMatchSnapshot(); + }); +}); + +(['verbose', 'debug', 'info', 'success', 'warning', 'error', 'write'] as const).forEach(method => { + describe(`#${method}()`, () => { + it(`sends a msg of type "${method}" to each writer with indent and arguments`, () => { + const log = new ToolingLog(); + const writeA = jest.fn(); + const writeB = jest.fn(); + + log.setWriters([{ write: writeA }, { write: writeB }]); + + if (method === 'error') { + const error = new Error('error message'); + error.stack = '... stack trace ...'; + log.error(error); + log.error('string message'); + } else { + log[method]('foo', 'bar', 'baz'); + } + + expect(writeA.mock.calls).toMatchSnapshot(); + expect(writeA.mock.calls).toEqual(writeB.mock.calls); + }); + }); +}); + +describe('#getWritten$()', () => { + async function testWrittenMsgs(writers: Writer[]) { + const log = new ToolingLog(); + log.setWriters(writers); + + const done$ = new Rx.Subject(); + const promise = log + .getWritten$() + .pipe( + takeUntil(done$), + toArray() + ) + .toPromise(); + + log.debug('foo'); + log.info('bar'); + log.verbose('baz'); + done$.next(); + + expect(await promise).toMatchSnapshot(); + } + + it('does not emit msg when no writers', async () => { + await testWrittenMsgs([]); + }); + + it('emits msg if all writers return true', async () => { + await testWrittenMsgs([{ write: jest.fn(() => true) }, { write: jest.fn(() => true) }]); + }); + + it('emits msg if some writers return true', async () => { + await testWrittenMsgs([{ write: jest.fn(() => true) }, { write: jest.fn(() => false) }]); + }); + + it('does not emit msg if all writers return false', async () => { + await testWrittenMsgs([{ write: jest.fn(() => false) }, { write: jest.fn(() => false) }]); + }); +}); diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log.ts new file mode 100644 index 0000000000000..c90d8d1ae1f0a --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log.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 * as Rx from 'rxjs'; + +import { ToolingLogTextWriter, ToolingLogTextWriterConfig } from './tooling_log_text_writer'; +import { Writer } from './writer'; +import { Message, MessageTypes } from './message'; + +export class ToolingLog { + private identWidth = 0; + private writers: Writer[]; + private readonly written$: Rx.Subject; + + constructor(writerConfig?: ToolingLogTextWriterConfig) { + this.writers = writerConfig ? [new ToolingLogTextWriter(writerConfig)] : []; + this.written$ = new Rx.Subject(); + } + + public indent(delta = 0) { + this.identWidth = Math.max(this.identWidth + delta, 0); + return this.identWidth; + } + + public verbose(...args: any[]) { + this.sendToWriters('verbose', args); + } + + public debug(...args: any[]) { + this.sendToWriters('debug', args); + } + + public info(...args: any[]) { + this.sendToWriters('info', args); + } + + public success(...args: any[]) { + this.sendToWriters('success', args); + } + + public warning(...args: any[]) { + this.sendToWriters('warning', args); + } + + public error(error: Error | string) { + this.sendToWriters('error', [error]); + } + + public write(...args: any[]) { + this.sendToWriters('write', args); + } + + public getWriters() { + return this.writers.slice(0); + } + + public setWriters(writers: Writer[]) { + this.writers = [...writers]; + } + + public getWritten$() { + return this.written$.asObservable(); + } + + private sendToWriters(type: MessageTypes, args: any[]) { + const msg = { + type, + indent: this.identWidth, + args, + }; + + let written = false; + for (const writer of this.writers) { + if (writer.write(msg)) { + written = true; + } + } + + if (written) { + this.written$.next(msg); + } + } +} diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.d.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.d.ts deleted file mode 100644 index 67311c5ceeeec..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.d.ts +++ /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. - */ - -import { LogLevel, ParsedLogLevel } from './log_levels'; -import { LogMessage } from './tooling_log'; - -export interface ToolingLogWriter { - write(msg: LogMessage): boolean; -} - -export interface WriteTarget { - write(chunk: string): void; -} - -export interface WriterConfig { - level: LogLevel; - writeTo: WriteTarget; -} - -export class ToolingLogTextWriter implements ToolingLogTextWriter { - public level: ParsedLogLevel; - public writeTo: WriteTarget; - - constructor(config: WriterConfig); - public write(msg: LogMessage): boolean; -} diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.js b/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.js deleted file mode 100644 index fa0db28687432..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.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 { format } from 'util'; - -import { magentaBright, yellow, red, blue, green, dim } from 'chalk'; - -import { parseLogLevel } from './log_levels'; - -const PREFIX_INDENT = ' '.repeat(6); -const MSG_PREFIXES = { - verbose: ` ${magentaBright('sill')} `, - debug: ` ${dim('debg')} `, - info: ` ${blue('info')} `, - success: ` ${green('succ')} `, - warning: ` ${yellow('warn')} `, - error: `${red('ERROR')} `, -}; - -function shouldWriteType(level, type) { - if (type === 'write') { - return true; - } - - return Boolean(level.flags[type === 'success' ? 'info' : type]); -} - -function stringifyError(error) { - if (typeof error !== 'string' && !(error instanceof Error)) { - error = new Error(`"${error}" thrown`); - } - - return error.stack || error.message || error; -} - -export class ToolingLogTextWriter { - constructor(config) { - this.level = parseLogLevel(config.level); - this.writeTo = config.writeTo; - - if (!this.writeTo || typeof this.writeTo.write !== 'function') { - throw new Error( - 'ToolingLogTextWriter requires the `writeTo` option be set to a stream (like process.stdout)' - ); - } - } - - write({ type, indent, args }) { - if (!shouldWriteType(this.level, type)) { - return false; - } - - const txt = type === 'error' ? stringifyError(args[0]) : format(...args); - const prefix = MSG_PREFIXES[type] || ''; - - (prefix + txt).split('\n').forEach((line, i) => { - let lineIndent = ''; - - if (indent > 0) { - // if we are indenting write some spaces followed by a symbol - lineIndent += ' '.repeat(indent - 1); - lineIndent += line.startsWith('-') ? '└' : '│'; - } - - if (line && prefix && i > 0) { - // apply additional indentation to lines after - // the first if this message gets a prefix - lineIndent += PREFIX_INDENT; - } - - this.writeTo.write(`${lineIndent}${line}\n`); - }); - - return true; - } -} diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.test.js b/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.test.js deleted file mode 100644 index ed859757c0e76..0000000000000 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.test.js +++ /dev/null @@ -1,98 +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 { ToolingLogTextWriter } from './tooling_log_text_writer'; - -it('throws error if created with invalid level', () => { - expect( - () => - new ToolingLogTextWriter({ - level: 'foo', - }) - ).toThrowErrorMatchingSnapshot(); -}); - -it("throws error if writeTo config is not defined or doesn't have a write method", () => { - expect(() => { - new ToolingLogTextWriter({ - level: 'verbose', - writeTo: null, - }); - }).toThrowErrorMatchingSnapshot(); - - expect(() => { - new ToolingLogTextWriter({ - level: 'verbose', - writeTo: 'foo', - }); - }).toThrowErrorMatchingSnapshot(); -}); - -const levels = ['silent', 'verbose', 'debug', 'info', 'warning', 'error']; -const types = ['verbose', 'debug', 'info', 'warning', 'error', 'success']; -for (const level of levels) { - for (const type of types) { - it(`level:${level}/type:${type} snapshots`, () => { - const write = jest.fn(); - const writer = new ToolingLogTextWriter({ - level, - writeTo: { - write, - }, - }); - - const written = writer.write({ - type: type, - indent: 0, - args: ['foo'], - }); - - expect(written).toMatchSnapshot('is written'); - - if (written) { - const output = write.mock.calls.reduce((acc, chunk) => `${acc}${chunk}`, ''); - expect(output).toMatchSnapshot('output'); - } - }); - } -} - -it('formats %s patterns and indents multi-line messages correctly', () => { - const write = jest.fn(); - const writer = new ToolingLogTextWriter({ - level: 'debug', - writeTo: { - write, - }, - }); - - writer.write({ - type: 'success', - indent: 10, - args: [ - '%s\n%O\n\n%d', - 'foo bar', - { foo: { bar: { 1: [1, 2, 3] } }, bar: { bar: { 1: [1, 2, 3] } } }, - Infinity, - ], - }); - - const output = write.mock.calls.reduce((acc, chunk) => `${acc}${chunk}`, ''); - expect(output).toMatchSnapshot(); -}); diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.test.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.test.ts new file mode 100644 index 0000000000000..8a908bfd2e3b6 --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.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 { ToolingLogTextWriter } from './tooling_log_text_writer'; + +it('throws error if created with invalid level', () => { + expect( + () => + new ToolingLogTextWriter({ + // @ts-ignore + level: 'foo', + }) + ).toThrowErrorMatchingSnapshot(); +}); + +it("throws error if writeTo config is not defined or doesn't have a write method", () => { + expect(() => { + new ToolingLogTextWriter({ + level: 'verbose', + // @ts-ignore + writeTo: null, + }); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new ToolingLogTextWriter({ + level: 'verbose', + // @ts-ignore + writeTo: 'foo', + }); + }).toThrowErrorMatchingSnapshot(); +}); + +const levels = ['silent', 'verbose', 'debug', 'info', 'warning', 'error'] as const; +const types = ['verbose', 'debug', 'info', 'warning', 'error', 'success'] as const; +for (const level of levels) { + for (const type of types) { + it(`level:${level}/type:${type} snapshots`, () => { + const write = jest.fn(); + const writer = new ToolingLogTextWriter({ + level, + writeTo: { + write, + }, + }); + + const written = writer.write({ + type, + indent: 0, + args: ['foo'], + }); + + expect(written).toMatchSnapshot('is written'); + + if (written) { + const output = write.mock.calls.reduce((acc, chunk) => `${acc}${chunk}`, ''); + expect(output).toMatchSnapshot('output'); + } + }); + } +} + +it('formats %s patterns and indents multi-line messages correctly', () => { + const write = jest.fn(); + const writer = new ToolingLogTextWriter({ + level: 'debug', + writeTo: { + write, + }, + }); + + writer.write({ + type: 'success', + indent: 10, + args: [ + '%s\n%O\n\n%d', + 'foo bar', + { foo: { bar: { 1: [1, 2, 3] } }, bar: { bar: { 1: [1, 2, 3] } } }, + Infinity, + ], + }); + + const output = write.mock.calls.reduce((acc, chunk) => `${acc}${chunk}`, ''); + expect(output).toMatchSnapshot(); +}); diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.ts b/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.ts new file mode 100644 index 0000000000000..65b625de9f308 --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.ts @@ -0,0 +1,113 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { format } from 'util'; + +import chalk from 'chalk'; + +import { LogLevel, parseLogLevel, ParsedLogLevel } from './log_levels'; +import { Writer } from './writer'; +import { Message, MessageTypes } from './message'; + +const { magentaBright, yellow, red, blue, green, dim } = chalk; +const PREFIX_INDENT = ' '.repeat(6); +const MSG_PREFIXES = { + verbose: ` ${magentaBright('sill')} `, + debug: ` ${dim('debg')} `, + info: ` ${blue('info')} `, + success: ` ${green('succ')} `, + warning: ` ${yellow('warn')} `, + error: `${red('ERROR')} `, +}; + +const has = (obj: T, key: any): key is keyof T => obj.hasOwnProperty(key); + +export interface ToolingLogTextWriterConfig { + level: LogLevel; + writeTo: { + write(s: string): void; + }; +} + +function shouldWriteType(level: ParsedLogLevel, type: MessageTypes) { + if (type === 'write') { + return true; + } + + return Boolean(level.flags[type === 'success' ? 'info' : type]); +} + +function stringifyError(error: string | Error) { + if (typeof error !== 'string' && !(error instanceof Error)) { + error = new Error(`"${error}" thrown`); + } + + if (typeof error === 'string') { + return error; + } + + return error.stack || error.message || error; +} + +export class ToolingLogTextWriter implements Writer { + public readonly level: ParsedLogLevel; + public readonly writeTo: { + write(msg: string): void; + }; + + constructor(config: ToolingLogTextWriterConfig) { + this.level = parseLogLevel(config.level); + this.writeTo = config.writeTo; + + if (!this.writeTo || typeof this.writeTo.write !== 'function') { + throw new Error( + 'ToolingLogTextWriter requires the `writeTo` option be set to a stream (like process.stdout)' + ); + } + } + + write({ type, indent, args }: Message) { + if (!shouldWriteType(this.level, type)) { + return false; + } + + const txt = type === 'error' ? stringifyError(args[0]) : format(args[0], ...args.slice(1)); + const prefix = has(MSG_PREFIXES, type) ? MSG_PREFIXES[type] : ''; + + (prefix + txt).split('\n').forEach((line, i) => { + let lineIndent = ''; + + if (indent > 0) { + // if we are indenting write some spaces followed by a symbol + lineIndent += ' '.repeat(indent - 1); + lineIndent += line.startsWith('-') ? '└' : '│'; + } + + if (line && prefix && i > 0) { + // apply additional indentation to lines after + // the first if this message gets a prefix + lineIndent += PREFIX_INDENT; + } + + this.writeTo.write(`${lineIndent}${line}\n`); + }); + + return true; + } +} diff --git a/packages/kbn-dev-utils/src/tooling_log/writer.ts b/packages/kbn-dev-utils/src/tooling_log/writer.ts new file mode 100644 index 0000000000000..858894bc52612 --- /dev/null +++ b/packages/kbn-dev-utils/src/tooling_log/writer.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 { Message } from './message'; + +export interface Writer { + write(msg: Message): boolean; +} diff --git a/packages/kbn-dev-utils/tsconfig.json b/packages/kbn-dev-utils/tsconfig.json index cb0d38840fffc..80eaaa297227c 100644 --- a/packages/kbn-dev-utils/tsconfig.json +++ b/packages/kbn-dev-utils/tsconfig.json @@ -1,7 +1,10 @@ { "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "target", + "declaration": true + }, "include": [ - "index.d.ts", - "src/**/*.d.ts" + "src/**/*" ], } diff --git a/packages/kbn-elastic-idx/package.json b/packages/kbn-elastic-idx/package.json index ccaa026bfcec4..e7a48509f63f3 100644 --- a/packages/kbn-elastic-idx/package.json +++ b/packages/kbn-elastic-idx/package.json @@ -17,8 +17,8 @@ "test": "jest" }, "devDependencies": { - "@babel/core": "7.4.5", - "@babel/plugin-transform-async-to-generator": "7.4.4", + "@babel/core": "^7.5.5", + "@babel/plugin-transform-async-to-generator": "^7.5.0", "jest": "^24.8.0", "typescript": "3.5.3" }, diff --git a/packages/kbn-es-query/babel.config.js b/packages/kbn-es-query/babel.config.js index 8f74cae512deb..68783433fc711 100644 --- a/packages/kbn-es-query/babel.config.js +++ b/packages/kbn-es-query/babel.config.js @@ -19,29 +19,15 @@ // We can't use common Kibana presets here because of babel versions incompatibility module.exports = { - plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread'], - presets: ['@babel/typescript'], env: { public: { presets: [ - [ - '@babel/preset-env', - { - modules: false - }, - ], + '@kbn/babel-preset/webpack_preset' ], }, server: { presets: [ - [ - '@babel/preset-env', - { - targets: { - node: 'current', - }, - }, - ], + '@kbn/babel-preset/node_preset' ], }, }, diff --git a/packages/kbn-es-query/package.json b/packages/kbn-es-query/package.json index 287e9b1b853ce..5ef1b6e125413 100644 --- a/packages/kbn-es-query/package.json +++ b/packages/kbn-es-query/package.json @@ -16,18 +16,13 @@ "@kbn/i18n": "1.0.0" }, "devDependencies": { - "@babel/cli": "7.4.4", - "@babel/core": "7.4.5", - "@babel/plugin-proposal-class-properties": "7.4.4", - "@babel/plugin-proposal-object-rest-spread": "7.4.4", - "@babel/preset-env": "7.4.5", - "@babel/preset-typescript": "7.3.3", + "@babel/cli": "^7.5.5", + "@babel/core": "^7.5.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@kbn/expect": "1.0.0", - "del": "^4.0.0", + "del": "^4.1.1", "getopts": "^2.2.4", - "supports-color": "^7.0.0", - "typescript": "3.5.3" + "supports-color": "^7.0.0" } } diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json index 21a7ed47718b4..1064d719af837 100644 --- a/packages/kbn-es/package.json +++ b/packages/kbn-es/package.json @@ -5,17 +5,17 @@ "license": "Apache-2.0", "private": true, "dependencies": { - "@elastic/elasticsearch": "^7.0.0-rc.2", + "@elastic/elasticsearch": "^7.3.0", "@kbn/dev-utils": "1.0.0", "abort-controller": "^2.0.3", - "chalk": "^2.4.1", + "chalk": "^2.4.2", "dedent": "^0.7.0", - "del": "^4.0.0", + "del": "^4.1.1", "execa": "^1.0.0", "getopts": "^2.2.4", "glob": "^7.1.2", "mkdirp": "^0.5.1", - "node-fetch": "^2.0.0", + "node-fetch": "^2.6.0", "simple-git": "^1.91.0", "tar-fs": "^1.16.3", "tree-kill": "^1.1.0", diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js index d779b3a542e6e..93c0f907d628d 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js @@ -21,7 +21,7 @@ const { resolve } = require('path'); const { debug } = require('./debug'); -const DEFAULT_PLUGIN_PATH = '../../kibana'; +const DEFAULT_PLUGIN_PATH = '../..'; /* * Resolves the path to Kibana, either from default setting or config diff --git a/packages/kbn-eslint-import-resolver-kibana/package.json b/packages/kbn-eslint-import-resolver-kibana/package.json index 144fdb5604231..14a9224924260 100755 --- a/packages/kbn-eslint-import-resolver-kibana/package.json +++ b/packages/kbn-eslint-import-resolver-kibana/package.json @@ -10,12 +10,12 @@ "url": "https://github.com/elastic/kibana/tree/master/packages/kbn-eslint-import-resolver-kibana" }, "dependencies": { - "debug": "^2.6.6", + "debug": "^2.6.9", "eslint-import-resolver-node": "0.3.2", "eslint-import-resolver-webpack": "0.11.1", "glob-all": "^3.1.0", - "lru-cache": "^4.1.3", + "lru-cache": "^4.1.5", "resolve": "^1.7.1", - "webpack": "^4.23.1" + "webpack": "^4.39.2" } } diff --git a/packages/kbn-eslint-plugin-eslint/package.json b/packages/kbn-eslint-plugin-eslint/package.json index af9006939adca..2f8f18103e146 100644 --- a/packages/kbn-eslint-plugin-eslint/package.json +++ b/packages/kbn-eslint-plugin-eslint/package.json @@ -5,11 +5,11 @@ "license": "Apache-2.0", "peerDependencies": { "eslint": "5.16.0", - "babel-eslint": "10.0.2" + "babel-eslint": "^10.0.3" }, "dependencies": { "micromatch": "3.1.10", "dedent": "^0.7.0", - "eslint-module-utils": "2.4.0" + "eslint-module-utils": "2.4.1" } } diff --git a/packages/kbn-i18n/babel.config.js b/packages/kbn-i18n/babel.config.js index 1ec84ecb115b2..4864854b280d5 100644 --- a/packages/kbn-i18n/babel.config.js +++ b/packages/kbn-i18n/babel.config.js @@ -17,25 +17,13 @@ * under the License. */ -// We can't use common Kibana presets here because of babel versions incompatibility module.exports = { - plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread'], - presets: ['@babel/preset-react', '@babel/typescript'], env: { web: { - presets: ['@babel/preset-env'], + presets: ['@kbn/babel-preset/webpack_preset'], }, node: { - presets: [ - [ - '@babel/preset-env', - { - targets: { - node: 'current', - }, - }, - ], - ], + presets: ['@kbn/babel-preset/node_preset'], }, }, ignore: ['**/*.test.ts', '**/*.test.tsx'], diff --git a/packages/kbn-i18n/package.json b/packages/kbn-i18n/package.json index d988e4870a95f..dff8a3f2f4b78 100644 --- a/packages/kbn-i18n/package.json +++ b/packages/kbn-i18n/package.json @@ -12,17 +12,13 @@ "kbn:watch": "node scripts/build --watch --source-maps" }, "devDependencies": { - "@babel/cli": "7.4.4", - "@babel/core": "7.4.5", - "@babel/plugin-proposal-class-properties": "7.4.4", - "@babel/plugin-proposal-object-rest-spread": "7.4.4", - "@babel/preset-env": "7.4.5", - "@babel/preset-react": "7.0.0", - "@babel/preset-typescript": "7.3.3", + "@babel/cli": "^7.5.5", + "@babel/core": "^7.5.5", + "@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": "^4.0.0", + "del": "^4.1.1", "getopts": "^2.2.4", "supports-color": "^7.0.0", "typescript": "3.5.3" diff --git a/packages/kbn-i18n/scripts/build.js b/packages/kbn-i18n/scripts/build.js index 6d53a8469b0e0..f4260d31d80fb 100644 --- a/packages/kbn-i18n/scripts/build.js +++ b/packages/kbn-i18n/scripts/build.js @@ -17,4 +17,79 @@ * under the License. */ -require('../tasks/build_cli'); +const { resolve } = require('path'); + +const del = require('del'); +const supportsColor = require('supports-color'); +const { run, withProcRunner } = require('@kbn/dev-utils'); + +const ROOT_DIR = resolve(__dirname, '..'); +const BUILD_DIR = resolve(ROOT_DIR, 'target'); + +const padRight = (width, str) => + str.length >= width ? str : `${str}${' '.repeat(width - str.length)}`; + +run( + async ({ log, flags }) => { + await withProcRunner(log, async proc => { + log.info('Deleting old output'); + await del(BUILD_DIR); + + const cwd = ROOT_DIR; + const env = { ...process.env }; + if (supportsColor.stdout) { + env.FORCE_COLOR = 'true'; + } + + log.info(`Starting babel and typescript${flags.watch ? ' in watch mode' : ''}`); + await Promise.all([ + ...['web', 'node'].map(subTask => + proc.run(padRight(10, `babel:${subTask}`), { + cmd: 'babel', + args: [ + 'src', + '--config-file', + require.resolve('../babel.config.js'), + '--out-dir', + resolve(BUILD_DIR, subTask), + '--extensions', + '.ts,.js,.tsx', + ...(flags.watch ? ['--watch'] : ['--quiet']), + ...(flags['source-maps'] ? ['--source-map', 'inline'] : []), + ], + wait: true, + env: { + ...env, + BABEL_ENV: subTask, + }, + cwd, + }) + ), + + proc.run(padRight(10, 'tsc'), { + cmd: 'tsc', + args: [ + '--emitDeclarationOnly', + ...(flags.watch ? ['--watch', '--preserveWatchOutput', 'true'] : []), + ...(flags['source-maps'] ? ['--declarationMap', 'true'] : []), + ], + wait: true, + env, + cwd, + }), + ]); + + log.success('Complete'); + }); + }, + { + description: 'Simple build tool for @kbn/i18n package', + flags: { + boolean: ['watch', 'source-maps'], + help: ` + --watch Run in watch mode + --source-maps Include sourcemaps + `, + }, + } +); diff --git a/packages/kbn-i18n/src/react/__snapshots__/provider.test.tsx.snap b/packages/kbn-i18n/src/react/__snapshots__/provider.test.tsx.snap index b584044979f06..c8a60fa069449 100644 --- a/packages/kbn-i18n/src/react/__snapshots__/provider.test.tsx.snap +++ b/packages/kbn-i18n/src/react/__snapshots__/provider.test.tsx.snap @@ -103,4 +103,8 @@ Object { } `; -exports[`I18nProvider renders children 1`] = ``; +exports[`I18nProvider renders children 1`] = ` + + + +`; diff --git a/packages/kbn-i18n/src/react/provider.test.tsx b/packages/kbn-i18n/src/react/provider.test.tsx index 6dabc806541cb..027b9242c4bc1 100644 --- a/packages/kbn-i18n/src/react/provider.test.tsx +++ b/packages/kbn-i18n/src/react/provider.test.tsx @@ -19,7 +19,6 @@ import { mount, shallow } from 'enzyme'; import * as React from 'react'; -import { intlShape } from 'react-intl'; import { injectI18n } from './inject'; import { I18nProvider } from './provider'; @@ -46,7 +45,7 @@ describe('I18nProvider', () => { , { childContextTypes: { - intl: intlShape, + intl: { formatMessage: jest.fn() }, }, } ); diff --git a/packages/kbn-i18n/src/react/provider.tsx b/packages/kbn-i18n/src/react/provider.tsx index a6bbfdb4d29b9..f5b237a88c161 100644 --- a/packages/kbn-i18n/src/react/provider.tsx +++ b/packages/kbn-i18n/src/react/provider.tsx @@ -22,47 +22,7 @@ import * as React from 'react'; import { IntlProvider } from 'react-intl'; import * as i18n from '../core'; -import { isPseudoLocale, translateUsingPseudoLocale } from '../core/pseudo_locale'; -import { injectI18n } from './inject'; - -/** - * To translate label that includes nested `FormattedMessage` instances React Intl - * replaces them with special placeholders (@__uid__@ELEMENT-uid-counter@__uid__@) - * and maps them back with nested translations after `formatMessage` processes - * original string, so we shouldn't modify these special placeholders with pseudo - * translations otherwise React Intl won't be able to properly replace placeholders. - * It's implementation detail of the React Intl, but since pseudo localization is dev - * only feature we should be fine here. - * @param message - */ -function translateFormattedMessageUsingPseudoLocale(message: string) { - const formattedMessageDelimiter = message.match(/@__.{10}__@/); - if (formattedMessageDelimiter !== null) { - return message - .split(formattedMessageDelimiter[0]) - .map(part => (part.startsWith('ELEMENT-') ? part : translateUsingPseudoLocale(part))) - .join(formattedMessageDelimiter[0]); - } - - return translateUsingPseudoLocale(message); -} - -/** - * If pseudo locale is detected, default intl.formatMessage should be decorated - * with the pseudo localization function. - * @param child I18nProvider child component. - */ -function wrapIntlFormatMessage(child: React.ReactElement) { - return React.createElement( - injectI18n(({ intl }) => { - const formatMessage = intl.formatMessage; - intl.formatMessage = (...args) => - translateFormattedMessageUsingPseudoLocale(formatMessage(...args)); - - return React.Children.only(child); - }) - ); -} +import { PseudoLocaleWrapper } from './pseudo_locale_wrapper'; /** * The library uses the provider pattern to scope an i18n context to a tree @@ -81,9 +41,7 @@ export class I18nProvider extends React.PureComponent { formats={i18n.getFormats()} textComponent={React.Fragment} > - {isPseudoLocale(i18n.getLocale()) && React.isValidElement(this.props.children) - ? wrapIntlFormatMessage(this.props.children) - : this.props.children} + {this.props.children} ); } diff --git a/packages/kbn-i18n/src/react/pseudo_locale_wrapper.tsx b/packages/kbn-i18n/src/react/pseudo_locale_wrapper.tsx new file mode 100644 index 0000000000000..db879fbae6ff1 --- /dev/null +++ b/packages/kbn-i18n/src/react/pseudo_locale_wrapper.tsx @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as PropTypes from 'prop-types'; +import * as React from 'react'; +import * as i18n from '../core'; +import { isPseudoLocale, translateUsingPseudoLocale } from '../core/pseudo_locale'; + +/** + * To translate label that includes nested `FormattedMessage` instances React Intl + * replaces them with special placeholders (@__uid__@ELEMENT-uid-counter@__uid__@) + * and maps them back with nested translations after `formatMessage` processes + * original string, so we shouldn't modify these special placeholders with pseudo + * translations otherwise React Intl won't be able to properly replace placeholders. + * It's implementation detail of the React Intl, but since pseudo localization is dev + * only feature we should be fine here. + * @param message + */ +function translateFormattedMessageUsingPseudoLocale(message: string) { + const formattedMessageDelimiter = message.match(/@__.{10}__@/); + if (formattedMessageDelimiter !== null) { + return message + .split(formattedMessageDelimiter[0]) + .map(part => (part.startsWith('ELEMENT-') ? part : translateUsingPseudoLocale(part))) + .join(formattedMessageDelimiter[0]); + } + + return translateUsingPseudoLocale(message); +} + +/** + * If the locale is our pseudo locale (e.g. en-xa), we override the + * intl.formatMessage function to display scrambled characters. We are + * overriding the context rather than using injectI18n, because the + * latter creates a new React component, which causes React diffs to + * be inefficient in some cases, and can cause React hooks to lose + * their state. + */ +export class PseudoLocaleWrapper extends React.PureComponent { + public static propTypes = { children: PropTypes.element.isRequired }; + + public static contextTypes = { + intl: PropTypes.object.isRequired, + }; + + constructor(props: { children: React.ReactNode }, context: any) { + super(props, context); + + if (isPseudoLocale(i18n.getLocale())) { + const formatMessage = context.intl.formatMessage; + context.intl.formatMessage = (...args: any[]) => + translateFormattedMessageUsingPseudoLocale(formatMessage(...args)); + } + } + + public render() { + return this.props.children; + } +} diff --git a/packages/kbn-i18n/tasks/build_cli.js b/packages/kbn-i18n/tasks/build_cli.js deleted file mode 100644 index 28f6b5adcc8b8..0000000000000 --- a/packages/kbn-i18n/tasks/build_cli.js +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const { resolve } = require('path'); - -const getopts = require('getopts'); -const del = require('del'); -const supportsColor = require('supports-color'); -const { ToolingLog, withProcRunner, pickLevelFromFlags } = require('@kbn/dev-utils'); - -const ROOT_DIR = resolve(__dirname, '..'); -const BUILD_DIR = resolve(ROOT_DIR, 'target'); - -const padRight = (width, str) => - str.length >= width ? str : `${str}${' '.repeat(width - str.length)}`; - -const unknownFlags = []; -const flags = getopts(process.argv, { - boolean: ['watch', 'help', 'source-maps'], - unknown(name) { - unknownFlags.push(name); - }, -}); - -const log = new ToolingLog({ - level: pickLevelFromFlags(flags), - writeTo: process.stdout, -}); - -if (unknownFlags.length) { - log.error(`Unknown flag(s): ${unknownFlags.join(', ')}`); - flags.help = true; - process.exitCode = 1; -} - -if (flags.help) { - log.info(` - Simple build tool for @kbn/i18n package - - --watch Run in watch mode - --source-maps Include sourcemaps - --help Show this message - `); - process.exit(); -} - -withProcRunner(log, async proc => { - log.info('Deleting old output'); - await del(BUILD_DIR); - - const cwd = ROOT_DIR; - const env = { ...process.env }; - if (supportsColor.stdout) { - env.FORCE_COLOR = 'true'; - } - - log.info(`Starting babel and typescript${flags.watch ? ' in watch mode' : ''}`); - await Promise.all([ - ...['web', 'node'].map(subTask => - proc.run(padRight(10, `babel:${subTask}`), { - cmd: 'babel', - args: [ - 'src', - '--config-file', - require.resolve('../babel.config.js'), - '--out-dir', - resolve(BUILD_DIR, subTask), - '--extensions', - '.ts,.js,.tsx', - ...(flags.watch ? ['--watch'] : ['--quiet']), - ...(flags['source-maps'] ? ['--source-map', 'inline'] : []), - ], - wait: true, - env: { - ...env, - BABEL_ENV: subTask, - }, - cwd, - }) - ), - - proc.run(padRight(10, 'tsc'), { - cmd: 'tsc', - args: [ - '--emitDeclarationOnly', - ...(flags.watch ? ['--watch', '--preserveWatchOutput', 'true'] : []), - ...(flags['source-maps'] ? ['--declarationMap', 'true'] : []), - ], - wait: true, - env, - cwd, - }), - ]); - - log.success('Complete'); -}).catch(error => { - log.error(error); - process.exit(1); -}); diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index 55a6b259022e8..a9b30c17e2927 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -9,30 +9,29 @@ "kbn:watch": "node scripts/build --dev --watch" }, "dependencies": { - "@babel/runtime": "7.4.5", + "@babel/runtime": "^7.5.5", "@kbn/i18n": "1.0.0", "lodash": "npm:@elastic/lodash@3.10.1-kibana3", "lodash.clone": "^4.5.0", "uuid": "3.3.2" }, "devDependencies": { - "@babel/cli": "7.4.4", - "@babel/core": "7.4.5", - "@babel/plugin-transform-runtime": "7.4.4", - "@babel/polyfill": "7.4.4", + "@babel/cli": "^7.5.5", + "@babel/core": "^7.5.5", + "@babel/plugin-transform-runtime": "^7.5.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", - "babel-loader": "8.0.6", - "copy-webpack-plugin": "^5.0.0", + "babel-loader": "^8.0.6", + "copy-webpack-plugin": "^5.0.4", "css-loader": "2.1.1", - "del": "^4.0.0", + "del": "^4.1.1", "getopts": "^2.2.4", "pegjs": "0.10.0", - "sass-loader": "^7.1.0", + "sass-loader": "^7.3.1", "style-loader": "0.23.1", "supports-color": "^7.0.0", - "url-loader": "2.0.0", - "webpack": "4.33.0", - "webpack-cli": "^3.1.2" + "url-loader": "2.1.0", + "webpack": "4.39.2", + "webpack-cli": "^3.3.7" } } diff --git a/packages/kbn-interpreter/src/common/index.d.ts b/packages/kbn-interpreter/src/common/index.d.ts index a8917b7a65df1..7201ccbb35635 100644 --- a/packages/kbn-interpreter/src/common/index.d.ts +++ b/packages/kbn-interpreter/src/common/index.d.ts @@ -19,4 +19,4 @@ export { Registry } from './lib/registry'; -export { fromExpression, Ast } from './lib/ast'; +export { fromExpression, toExpression, Ast } from './lib/ast'; diff --git a/packages/kbn-interpreter/src/common/lib/ast.d.ts b/packages/kbn-interpreter/src/common/lib/ast.d.ts index 2b0328bda9392..a4ee235359463 100644 --- a/packages/kbn-interpreter/src/common/lib/ast.d.ts +++ b/packages/kbn-interpreter/src/common/lib/ast.d.ts @@ -20,3 +20,4 @@ export type Ast = unknown; export declare function fromExpression(expression: string): Ast; +export declare function toExpression(astObj: Ast, type?: string): string; diff --git a/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js b/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js new file mode 100644 index 0000000000000..18e161e0ce925 --- /dev/null +++ b/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js @@ -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. + */ + +/* eslint-disable no-restricted-syntax */ +import { spawn } from 'child_process'; +import { resolve } from 'path'; +import util from 'util'; +import { stat, readFileSync } from 'fs'; +import { snakeCase } from 'lodash'; +import del from 'del'; +import { withProcRunner, ToolingLog } from '@kbn/dev-utils'; +import { createEsTestCluster } from '@kbn/test'; +import execa from 'execa'; + +const statP = util.promisify(stat); +const ROOT_DIR = resolve(__dirname, '../../../'); +const oneMinute = 60000; + +describe(`running the plugin-generator via 'node scripts/generate_plugin.js plugin-name' with default config`, () => { + const pluginName = 'ispec-plugin'; + const snakeCased = snakeCase(pluginName); + const generatedPath = resolve(ROOT_DIR, `plugins/${snakeCased}`); + const collect = xs => data => xs.push(data + ''); // Coerce from Buffer to String + + beforeAll(() => { + jest.setTimeout(oneMinute * 10); + }); + + beforeAll(done => { + const create = spawn(process.execPath, ['scripts/generate_plugin.js', pluginName], { + cwd: ROOT_DIR, + }); + create.stdout.on('data', function selectDefaults() { + create.stdin.write('\n'); // Generate a plugin with default options. + }); + create.on('close', done); + }); + + afterAll(() => { + del.sync(generatedPath, { force: true }); + }); + + it(`should succeed on creating a plugin in a directory named 'plugins/${snakeCased}`, async () => { + const stats = await statP(generatedPath); + expect(stats.isDirectory()).toBe(true); + }); + + it(`should create an internationalization config file with a blank line appended to satisfy the parser`, async () => { + // Link to the error that happens when the blank line is not there: + // https://github.com/elastic/kibana/pull/45044#issuecomment-530092627 + const intlFile = `${generatedPath}/.i18nrc.json`; + expect(readFileSync(intlFile, 'utf8').endsWith('\n\n')).toBe(true); + }); + + describe(`then running`, () => { + it(`'yarn test:browser' should exit 0`, async () => { + await execa('yarn', ['test:browser'], { cwd: generatedPath }); + }); + + it(`'yarn test:server' should exit 0`, async () => { + await execa('yarn', ['test:server'], { cwd: generatedPath }); + }); + + it(`'yarn build' should exit 0`, async () => { + await execa('yarn', ['build'], { cwd: generatedPath }); + }); + + it(`'yarn start' should result in the spec plugin being initialized on kibana's stdout`, async () => { + const log = new ToolingLog(); + const es = createEsTestCluster({ license: 'basic', log }); + await es.start(); + await withProcRunner(log, async proc => { + await proc.run('kibana', { + cmd: 'yarn', + args: ['start', '--optimize.enabled=false', '--logging.json=false'], + cwd: generatedPath, + wait: /ispec_plugin.+Status changed from uninitialized to green - Ready/, + }); + await proc.stop('kibana'); + }); + await es.stop(); + }); + + it(`'yarn preinstall' should exit 0`, async () => { + await execa('yarn', ['preinstall'], { cwd: generatedPath }); + }); + + it(`'yarn lint' should exit 0`, async () => { + await execa('yarn', ['lint'], { cwd: generatedPath }); + }); + + it(`'yarn kbn --help' should print out the kbn help msg`, done => { + const helpMsg = ` +usage: kbn [] + +By default commands are run for Kibana itself, all packages in the 'packages/' +folder and for all plugins in './plugins' and '../kibana-extra'. + +Available commands: + + bootstrap - Install dependencies and crosslink projects + clean - Remove the node_modules and target directories from all projects. + run - Run script defined in package.json in each package that contains that script. + watch - Runs \`kbn:watch\` script for every project. + +Global options: + + -e, --exclude Exclude specified project. Can be specified multiple times to exclude multiple projects, e.g. '-e kibana -e @kbn/pm'. + -i, --include Include only specified projects. If left unspecified, it defaults to including all projects. + --oss Do not include the x-pack when running command. + --skip-kibana-plugins Filter all plugins in ./plugins and ../kibana-extra when running command. +`; + const outData = []; + const kbnHelp = spawn('yarn', ['kbn', '--help'], { cwd: generatedPath }); + kbnHelp.stdout.on('data', collect(outData)); + kbnHelp.on('close', () => { + expect(outData.join('\n')).toContain(helpMsg); + done(); + }); + }); + + it(`'yarn es --help' should print out the es help msg`, done => { + const helpMsg = ` +usage: es [] + +Assists with running Elasticsearch for Kibana development + +Available commands: + + snapshot - Downloads and run from a nightly snapshot + source - Build and run from source + archive - Install and run from an Elasticsearch tar + build_snapshots - Build and collect ES snapshots + +Global options: + + --help +`; + const outData = []; + const kbnHelp = spawn('yarn', ['es', '--help'], { cwd: generatedPath }); + kbnHelp.stdout.on('data', collect(outData)); + kbnHelp.on('close', () => { + expect(outData.join('\n')).toContain(helpMsg); + done(); + }); + }); + }); +}); diff --git a/packages/kbn-plugin-generator/package.json b/packages/kbn-plugin-generator/package.json index a26371be863db..74ccbd8e758b5 100644 --- a/packages/kbn-plugin-generator/package.json +++ b/packages/kbn-plugin-generator/package.json @@ -4,7 +4,7 @@ "private": true, "version": "1.0.0", "dependencies": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "dedent": "^0.7.0", "execa": "^1.0.0", "getopts": "^2.2.4", diff --git a/packages/kbn-plugin-generator/sao_template/sao.js b/packages/kbn-plugin-generator/sao_template/sao.js index 874735593d442..3eb88f53190a1 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.js +++ b/packages/kbn-plugin-generator/sao_template/sao.js @@ -80,7 +80,7 @@ module.exports = function({ name }) { }, move: { gitignore: '.gitignore', - eslintrc: '.eslintrc', + 'eslintrc.js': '.eslintrc.js', 'package_template.json': 'package.json', }, data: answers => diff --git a/packages/kbn-plugin-generator/sao_template/sao.test.js b/packages/kbn-plugin-generator/sao_template/sao.test.js index 77c9b4533b9ca..80149c008dad8 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.test.js +++ b/packages/kbn-plugin-generator/sao_template/sao.test.js @@ -198,6 +198,6 @@ describe('plugin generator sao integration', () => { it('includes dotfiles', async () => { const res = await sao.mockPrompt(template); expect(res.files['.gitignore']).toBeTruthy(); - expect(res.files['.eslintrc']).toBeTruthy(); + expect(res.files['.eslintrc.js']).toBeTruthy(); }); }); diff --git a/packages/kbn-plugin-generator/sao_template/template/.i18nrc.json b/packages/kbn-plugin-generator/sao_template/template/.i18nrc.json index 3fb2834877898..1a8aea8853876 100644 --- a/packages/kbn-plugin-generator/sao_template/template/.i18nrc.json +++ b/packages/kbn-plugin-generator/sao_template/template/.i18nrc.json @@ -6,3 +6,4 @@ "translations/zh-CN.json" ] } + diff --git a/packages/kbn-plugin-generator/sao_template/template/eslintrc b/packages/kbn-plugin-generator/sao_template/template/eslintrc deleted file mode 100755 index e54900aa30249..0000000000000 --- a/packages/kbn-plugin-generator/sao_template/template/eslintrc +++ /dev/null @@ -1,7 +0,0 @@ ---- -extends: "@elastic/kibana" - -settings: - import/resolver: - '@elastic/eslint-import-resolver-kibana': - rootPackageName: '<%= snakeCase(name) %>' diff --git a/packages/kbn-plugin-generator/sao_template/template/eslintrc.js b/packages/kbn-plugin-generator/sao_template/template/eslintrc.js new file mode 100755 index 0000000000000..e1dfadc212b7e --- /dev/null +++ b/packages/kbn-plugin-generator/sao_template/template/eslintrc.js @@ -0,0 +1,24 @@ +module.exports = { + root: true, + extends: ['@elastic/eslint-config-kibana', 'plugin:@elastic/eui/recommended'], + settings: { + 'import/resolver': { + '@kbn/eslint-import-resolver-kibana': { + rootPackageName: '<%= snakeCase(name) %>', + }, + }, + }, + overrides: [ + { + files: ['**/public/**/*'], + settings: { + 'import/resolver': { + '@kbn/eslint-import-resolver-kibana': { + forceNode: false, + rootPackageName: '<%= snakeCase(name) %>', + }, + }, + }, + }, + ] +}; diff --git a/packages/kbn-plugin-generator/sao_template/template/index.js b/packages/kbn-plugin-generator/sao_template/template/index.js index 40ed14af52c6e..0a3e16cf71e49 100755 --- a/packages/kbn-plugin-generator/sao_template/template/index.js +++ b/packages/kbn-plugin-generator/sao_template/template/index.js @@ -43,39 +43,39 @@ export default function (kibana) { init(server, options) { // eslint-disable-line no-unused-vars <%_ if (generateApp) { -%> - const xpackMainPlugin = server.plugins.xpack_main; - if (xpackMainPlugin) { - const featureId = '<%= snakeCase(name) %>'; + const xpackMainPlugin = server.plugins.xpack_main; + if (xpackMainPlugin) { + const featureId = '<%= snakeCase(name) %>'; - xpackMainPlugin.registerFeature({ - id: featureId, - name: i18n.translate('<%= camelCase(name) %>.featureRegistry.featureName', { - defaultMessage: '<%= name %>', - }), - navLinkId: featureId, - icon: 'questionInCircle', - app: [featureId, 'kibana'], - catalogue: [], - privileges: { - all: { - api: [], - savedObject: { - all: [], - read: [], - }, - ui: ['show'], + xpackMainPlugin.registerFeature({ + id: featureId, + name: i18n.translate('<%= camelCase(name) %>.featureRegistry.featureName', { + defaultMessage: '<%= name %>', + }), + navLinkId: featureId, + icon: 'questionInCircle', + app: [featureId, 'kibana'], + catalogue: [], + privileges: { + all: { + api: [], + savedObject: { + all: [], + read: [], }, - read: { - api: [], - savedObject: { - all: [], - read: [], - }, - ui: ['show'], + ui: ['show'], + }, + read: { + api: [], + savedObject: { + all: [], + read: [], }, + ui: ['show'], }, - }); - } + }, + }); + } <%_ } -%> <%_ if (generateApi) { -%> diff --git a/packages/kbn-plugin-generator/sao_template/template/public/components/main/index.js b/packages/kbn-plugin-generator/sao_template/template/public/components/main/index.js index b8dd6dff2e533..68710baa1bee8 100644 --- a/packages/kbn-plugin-generator/sao_template/template/public/components/main/index.js +++ b/packages/kbn-plugin-generator/sao_template/template/public/components/main/index.js @@ -1 +1 @@ -export { Main } from './main'; \ No newline at end of file +export { Main } from './main'; diff --git a/packages/kbn-plugin-helpers/lib/config_file.js b/packages/kbn-plugin-helpers/lib/config_file.js index fc359f838f67d..5b8be836998e4 100644 --- a/packages/kbn-plugin-helpers/lib/config_file.js +++ b/packages/kbn-plugin-helpers/lib/config_file.js @@ -47,8 +47,9 @@ module.exports = function(root) { const deprecationMsg = 'has been removed from `@kbn/plugin-helpers`. ' + - 'During development your plugin must be located in `../kibana-extra/{pluginName}` ' + - 'relative to the Kibana directory to work with this package.\n'; + 'During development your plugin must live in `./plugins/{pluginName}` ' + + 'inside the Kibana folder or `../kibana-extra/{pluginName}` ' + + 'relative to the Kibana folder to work with this package.\n'; if (config.kibanaRoot) { throw new Error('The `kibanaRoot` config option ' + deprecationMsg); diff --git a/packages/kbn-plugin-helpers/lib/plugin_config.js b/packages/kbn-plugin-helpers/lib/plugin_config.js index 62a333728771f..07bbbfedc15da 100644 --- a/packages/kbn-plugin-helpers/lib/plugin_config.js +++ b/packages/kbn-plugin-helpers/lib/plugin_config.js @@ -24,7 +24,8 @@ const configFile = require('./config_file'); module.exports = function(root) { if (!root) root = process.cwd(); - const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'))); + const pluginPackageJsonPath = resolve(root, 'package.json'); + const pkg = JSON.parse(readFileSync(pluginPackageJsonPath)); const config = configFile(root); const buildSourcePatterns = [ @@ -35,10 +36,23 @@ module.exports = function(root) { '{lib,public,server,webpackShims,translations}/**/*', ]; + const kibanaExtraDir = resolve(root, '../../kibana'); + const kibanaPluginsDir = resolve(root, '../../'); + const isPluginOnKibanaExtra = pluginPackageJsonPath.includes(kibanaExtraDir); + const isPluginXpack = pkg.name === 'x-pack'; + + if (isPluginOnKibanaExtra && !isPluginXpack) { + console.warn( + `In the future we will disable ../kibana-extra/{pluginName}. You should move your plugin ${pkg.name} as soon as possible to ./plugins/{pluginName}` + ); + } + + const kibanaRootWhenNotXpackPlugin = isPluginOnKibanaExtra ? kibanaExtraDir : kibanaPluginsDir; + return Object.assign( { root: root, - kibanaRoot: pkg.name === 'x-pack' ? resolve(root, '..') : resolve(root, '../../kibana'), + kibanaRoot: isPluginXpack ? resolve(root, '..') : kibanaRootWhenNotXpackPlugin, serverTestPatterns: ['server/**/__tests__/**/*.js'], buildSourcePatterns: buildSourcePatterns, skipInstallDependencies: false, diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index 2777103b2d1b7..ce496abe9c7f1 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -13,10 +13,10 @@ "@kbn/babel-preset": "1.0.0" }, "dependencies": { - "@babel/core": "^7.4.4", + "@babel/core": "^7.5.5", "argv-split": "^2.0.1", "commander": "^3.0.0", - "del": "^4.0.0", + "del": "^4.1.1", "execa": "^1.0.0", "globby": "^8.0.1", "gulp-babel": "^8.0.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index fd8f2aba42c41..8953cee42d036 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,21 +94,21 @@ __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__(371); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(403); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(35); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(36); /* 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__(53); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(54); /* 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__(134); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(162); /* 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__(135); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(163); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -152,8 +152,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(361); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(33); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(393); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2502,9 +2502,9 @@ module.exports = require("path"); __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__(18); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(136); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(159); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(160); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(164); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(191); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(192); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2544,9 +2544,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(33); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(34); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(35); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(35); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(36); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2631,7 +2631,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(33); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2712,7 +2712,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var mkdirp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(31); /* harmony import */ var mkdirp__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(mkdirp__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(32); +/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(33); /* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ncp__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__); @@ -2847,7 +2847,8 @@ var fs = __webpack_require__(22) var mkdir = __webpack_require__(31) , path = __webpack_require__(16) - , shebangExpr = /^#\!\s*(?:\/usr\/bin\/env)?\s*([^ \t]+)(.*)$/ + , toBatchSyntax = __webpack_require__(32) + , shebangExpr = /^#\!\s*(?:\/usr\/bin\/env)?\s*([^ \t]+=[^ \t]+\s+)*\s*([^ \t]+)(.*)$/ function cmdShimIfExists (from, to, cb) { fs.stat(from, function (er) { @@ -2895,51 +2896,70 @@ function writeShim (from, to, cb) { if (er) return writeShim_(from, to, null, null, cb) var firstLine = data.trim().split(/\r*\n/)[0] , shebang = firstLine.match(shebangExpr) - if (!shebang) return writeShim_(from, to, null, null, cb) - var prog = shebang[1] - , args = shebang[2] || "" - return writeShim_(from, to, prog, args, cb) + if (!shebang) return writeShim_(from, to, null, null, null, cb) + var vars = shebang[1] || "" + , prog = shebang[2] + , args = shebang[3] || "" + return writeShim_(from, to, prog, args, vars, cb) }) }) } -function writeShim_ (from, to, prog, args, cb) { + +function writeShim_ (from, to, prog, args, variables, cb) { var shTarget = path.relative(path.dirname(to), from) , target = shTarget.split("/").join("\\") , longProg , shProg = prog && prog.split("\\").join("/") , shLongProg + , pwshProg = shProg && "\"" + shProg + "$exe\"" + , pwshLongProg shTarget = shTarget.split("\\").join("/") args = args || "" + variables = variables || "" if (!prog) { prog = "\"%~dp0\\" + target + "\"" shProg = "\"$basedir/" + shTarget + "\"" + pwshProg = shProg args = "" target = "" shTarget = "" } else { longProg = "\"%~dp0\\" + prog + ".exe\"" shLongProg = "\"$basedir/" + prog + "\"" + pwshLongProg = "\"$basedir/" + prog + "$exe\"" target = "\"%~dp0\\" + target + "\"" shTarget = "\"$basedir/" + shTarget + "\"" } + // @SETLOCAL + // // @IF EXIST "%~dp0\node.exe" ( - // "%~dp0\node.exe" "%~dp0\.\node_modules\npm\bin\npm-cli.js" %* + // @SET "_prog=%~dp0\node.exe" // ) ELSE ( - // SETLOCAL - // SET PATHEXT=%PATHEXT:;.JS;=;% - // node "%~dp0\.\node_modules\npm\bin\npm-cli.js" %* + // @SET "_prog=node" + // @SET PATHEXT=%PATHEXT:;.JS;=;% // ) + // + // "%_prog%" "%~dp0\.\node_modules\npm\bin\npm-cli.js" %* + // @ENDLOCAL var cmd if (longProg) { - cmd = "@IF EXIST " + longProg + " (\r\n" - + " " + longProg + " " + args + " " + target + " %*\r\n" + shLongProg = shLongProg.trim(); + args = args.trim(); + var variableDeclarationsAsBatch = toBatchSyntax.convertToSetCommands(variables) + cmd = "@SETLOCAL\r\n" + + variableDeclarationsAsBatch + + "\r\n" + + "@IF EXIST " + longProg + " (\r\n" + + " @SET \"_prog=" + longProg.replace(/(^")|("$)/g, '') + "\"\r\n" + ") ELSE (\r\n" - + " @SETLOCAL\r\n" + + " @SET \"_prog=" + prog.replace(/(^")|("$)/g, '') + "\"\r\n" + " @SET PATHEXT=%PATHEXT:;.JS;=;%\r\n" - + " " + prog + " " + args + " " + target + " %*\r\n" - + ")" + + ")\r\n" + + "\r\n" + + "\"%_prog%\" " + args + " " + target + " %*\r\n" + + '@ENDLOCAL\r\n' } else { cmd = "@" + prog + " " + args + " " + target + " %*\r\n" } @@ -2948,7 +2968,7 @@ function writeShim_ (from, to, prog, args, cb) { // basedir=`dirname "$0"` // // case `uname` in - // *CYGWIN*) basedir=`cygpath -w "$basedir"`;; + // *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; // esac // // if [ -x "$basedir/node.exe" ]; then @@ -2962,30 +2982,76 @@ function writeShim_ (from, to, prog, args, cb) { var sh = "#!/bin/sh\n" - if (shLongProg) { - sh = sh - + "basedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\n" - + "\n" - + "case `uname` in\n" - + " *CYGWIN*) basedir=`cygpath -w \"$basedir\"`;;\n" - + "esac\n" - + "\n" + sh = sh + + "basedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\n" + + "\n" + + "case `uname` in\n" + + " *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w \"$basedir\"`;;\n" + + "esac\n" + + "\n" + if (shLongProg) { sh = sh + "if [ -x "+shLongProg+" ]; then\n" - + " " + shLongProg + " " + args + " " + shTarget + " \"$@\"\n" + + " " + variables + shLongProg + " " + args + " " + shTarget + " \"$@\"\n" + " ret=$?\n" + "else \n" - + " " + shProg + " " + args + " " + shTarget + " \"$@\"\n" + + " " + variables + shProg + " " + args + " " + shTarget + " \"$@\"\n" + " ret=$?\n" + "fi\n" + "exit $ret\n" } else { - sh = shProg + " " + args + " " + shTarget + " \"$@\"\n" + sh = sh + + shProg + " " + args + " " + shTarget + " \"$@\"\n" + "exit $?\n" } - var then = times(2, next, cb) + // #!/usr/bin/env pwsh + // $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + // + // $ret=0 + // $exe = "" + // if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + // # Fix case when both the Windows and Linux builds of Node + // # are installed in the same directory + // $exe = ".exe" + // } + // if (Test-Path "$basedir/node") { + // & "$basedir/node$exe" "$basedir/node_modules/npm/bin/npm-cli.js" $args + // $ret=$LASTEXITCODE + // } else { + // & "node$exe" "$basedir/node_modules/npm/bin/npm-cli.js" $args + // $ret=$LASTEXITCODE + // } + // exit $ret + var pwsh = "#!/usr/bin/env pwsh\n" + + "$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent\n" + + "\n" + + "$exe=\"\"\n" + + "if ($PSVersionTable.PSVersion -lt \"6.0\" -or $IsWindows) {\n" + + " # Fix case when both the Windows and Linux builds of Node\n" + + " # are installed in the same directory\n" + + " $exe=\".exe\"\n" + + "}\n" + if (shLongProg) { + pwsh = pwsh + + "$ret=0\n" + + "if (Test-Path " + pwshLongProg + ") {\n" + + " & " + pwshLongProg + " " + args + " " + shTarget + " $args\n" + + " $ret=$LASTEXITCODE\n" + + "} else {\n" + + " & " + pwshProg + " " + args + " " + shTarget + " $args\n" + + " $ret=$LASTEXITCODE\n" + + "}\n" + + "exit $ret\n" + } else { + pwsh = pwsh + + "& " + pwshProg + " " + args + " " + shTarget + " $args\n" + + "exit $LASTEXITCODE\n" + } + + var then = times(3, next, cb) + fs.writeFile(to + ".ps1", pwsh, "utf8", then) fs.writeFile(to + ".cmd", cmd, "utf8", then) fs.writeFile(to, sh, "utf8", then) function next () { @@ -2995,8 +3061,9 @@ function writeShim_ (from, to, prog, args, cb) { function chmodShim (to, cb) { var then = times(2, cb, cb) - fs.chmod(to, 0755, then) - fs.chmod(to + ".cmd", 0755, then) + fs.chmod(to, "0755", then) + fs.chmod(to + ".cmd", "0755", then) + fs.chmod(to + ".ps1", "0755", then) } function times(n, ok, cb) { @@ -3904,6 +3971,64 @@ mkdirP.sync = function sync (p, opts, made) { /***/ }), /* 32 */ +/***/ (function(module, exports) { + +exports.replaceDollarWithPercentPair = replaceDollarWithPercentPair +exports.convertToSetCommand = convertToSetCommand +exports.convertToSetCommands = convertToSetCommands + +function convertToSetCommand(key, value) { + var line = "" + key = key || "" + key = key.trim() + value = value || "" + value = value.trim() + if(key && value && value.length > 0) { + line = "@SET " + key + "=" + replaceDollarWithPercentPair(value) + "\r\n" + } + return line +} + +function extractVariableValuePairs(declarations) { + var pairs = {} + declarations.map(function(declaration) { + var split = declaration.split("=") + pairs[split[0]]=split[1] + }) + return pairs +} + +function convertToSetCommands(variableString) { + var variableValuePairs = extractVariableValuePairs(variableString.split(" ")) + var variableDeclarationsAsBatch = "" + Object.keys(variableValuePairs).forEach(function (key) { + variableDeclarationsAsBatch += convertToSetCommand(key, variableValuePairs[key]) + }) + return variableDeclarationsAsBatch +} + +function replaceDollarWithPercentPair(value) { + var dollarExpressions = /\$\{?([^\$@#\?\- \t{}:]+)\}?/g + var result = "" + var startIndex = 0 + value = value || "" + do { + var match = dollarExpressions.exec(value) + if(match) { + var betweenMatches = value.substring(startIndex, match.index) || "" + result += betweenMatches + "%" + match[1] + "%" + startIndex = dollarExpressions.lastIndex + } + } while (dollarExpressions.lastIndex > 0) + result += value.substr(startIndex) + return result +} + + + + +/***/ }), +/* 33 */ /***/ (function(module, exports, __webpack_require__) { var fs = __webpack_require__(23), @@ -4170,7 +4295,7 @@ function ncp (source, dest, options, callback) { /***/ }), -/* 33 */ +/* 34 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4208,7 +4333,7 @@ const log = { }; /***/ }), -/* 34 */ +/* 35 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4274,7 +4399,7 @@ async function parallelize(items, fn, concurrency = 4) { } /***/ }), -/* 35 */ +/* 36 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4283,15 +4408,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__(36); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(37); /* 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__(16); /* 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__(29); /* 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__(52); -/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53); -/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(134); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(53); +/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(54); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(162); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -4488,7 +4613,7 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, { } /***/ }), -/* 36 */ +/* 37 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -4534,26 +4659,26 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, { module.exports = glob var fs = __webpack_require__(23) -var rp = __webpack_require__(37) -var minimatch = __webpack_require__(39) +var rp = __webpack_require__(38) +var minimatch = __webpack_require__(40) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(43) -var EE = __webpack_require__(45).EventEmitter +var inherits = __webpack_require__(44) +var EE = __webpack_require__(46).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(46) -var globSync = __webpack_require__(47) -var common = __webpack_require__(48) +var isAbsolute = __webpack_require__(47) +var globSync = __webpack_require__(48) +var common = __webpack_require__(49) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts var ownProp = common.ownProp -var inflight = __webpack_require__(49) +var inflight = __webpack_require__(50) var util = __webpack_require__(29) var childrenIgnored = common.childrenIgnored var isIgnored = common.isIgnored -var once = __webpack_require__(51) +var once = __webpack_require__(52) function glob (pattern, options, cb) { if (typeof options === 'function') cb = options, options = {} @@ -5284,7 +5409,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 37 */ +/* 38 */ /***/ (function(module, exports, __webpack_require__) { module.exports = realpath @@ -5300,7 +5425,7 @@ var origRealpathSync = fs.realpathSync var version = process.version var ok = /^v[0-5]\./.test(version) -var old = __webpack_require__(38) +var old = __webpack_require__(39) function newError (er) { return er && er.syscall === 'realpath' && ( @@ -5356,7 +5481,7 @@ function unmonkeypatch () { /***/ }), -/* 38 */ +/* 39 */ /***/ (function(module, exports, __webpack_require__) { // Copyright Joyent, Inc. and other Node contributors. @@ -5665,7 +5790,7 @@ exports.realpath = function realpath(p, cache, cb) { /***/ }), -/* 39 */ +/* 40 */ /***/ (function(module, exports, __webpack_require__) { module.exports = minimatch @@ -5677,7 +5802,7 @@ try { } catch (er) {} var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} -var expand = __webpack_require__(40) +var expand = __webpack_require__(41) var plTypes = { '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, @@ -6594,11 +6719,11 @@ function regExpEscape (s) { /***/ }), -/* 40 */ +/* 41 */ /***/ (function(module, exports, __webpack_require__) { -var concatMap = __webpack_require__(41); -var balanced = __webpack_require__(42); +var concatMap = __webpack_require__(42); +var balanced = __webpack_require__(43); module.exports = expandTop; @@ -6801,7 +6926,7 @@ function expand(str, isTop) { /***/ }), -/* 41 */ +/* 42 */ /***/ (function(module, exports) { module.exports = function (xs, fn) { @@ -6820,7 +6945,7 @@ var isArray = Array.isArray || function (xs) { /***/ }), -/* 42 */ +/* 43 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6886,7 +7011,7 @@ function range(a, b, str) { /***/ }), -/* 43 */ +/* 44 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -6894,12 +7019,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(44); + module.exports = __webpack_require__(45); } /***/ }), -/* 44 */ +/* 45 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -6928,13 +7053,13 @@ if (typeof Object.create === 'function') { /***/ }), -/* 45 */ +/* 46 */ /***/ (function(module, exports) { module.exports = require("events"); /***/ }), -/* 46 */ +/* 47 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6961,22 +7086,22 @@ module.exports.win32 = win32; /***/ }), -/* 47 */ +/* 48 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync globSync.GlobSync = GlobSync var fs = __webpack_require__(23) -var rp = __webpack_require__(37) -var minimatch = __webpack_require__(39) +var rp = __webpack_require__(38) +var minimatch = __webpack_require__(40) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(36).Glob +var Glob = __webpack_require__(37).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(46) -var common = __webpack_require__(48) +var isAbsolute = __webpack_require__(47) +var common = __webpack_require__(49) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -7453,7 +7578,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 48 */ +/* 49 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -7471,8 +7596,8 @@ function ownProp (obj, field) { } var path = __webpack_require__(16) -var minimatch = __webpack_require__(39) -var isAbsolute = __webpack_require__(46) +var minimatch = __webpack_require__(40) +var isAbsolute = __webpack_require__(47) var Minimatch = minimatch.Minimatch function alphasorti (a, b) { @@ -7699,12 +7824,12 @@ function childrenIgnored (self, path) { /***/ }), -/* 49 */ +/* 50 */ /***/ (function(module, exports, __webpack_require__) { -var wrappy = __webpack_require__(50) +var wrappy = __webpack_require__(51) var reqs = Object.create(null) -var once = __webpack_require__(51) +var once = __webpack_require__(52) module.exports = wrappy(inflight) @@ -7759,7 +7884,7 @@ function slice (args) { /***/ }), -/* 50 */ +/* 51 */ /***/ (function(module, exports) { // Returns a wrapper function that returns a wrapped callback @@ -7798,10 +7923,10 @@ function wrappy (fn, cb) { /***/ }), -/* 51 */ +/* 52 */ /***/ (function(module, exports, __webpack_require__) { -var wrappy = __webpack_require__(50) +var wrappy = __webpack_require__(51) module.exports = wrappy(once) module.exports.strict = wrappy(onceStrict) @@ -7846,7 +7971,7 @@ function onceStrict (fn) { /***/ }), -/* 52 */ +/* 53 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -7879,7 +8004,7 @@ class CliError extends Error { } /***/ }), -/* 53 */ +/* 54 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -7893,11 +8018,13 @@ __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 util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(52); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(54); -/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(95); -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(55); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(119); +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(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 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; } @@ -7963,7 +8090,7 @@ class Project { this.targetLocation = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(this.path, 'target'); this.productionDependencies = this.json.dependencies || {}; this.devDependencies = this.json.devDependencies || {}; - this.allDependencies = _objectSpread({}, this.devDependencies, this.productionDependencies); + this.allDependencies = _objectSpread({}, this.devDependencies, {}, this.productionDependencies); this.isWorkspaceRoot = this.json.hasOwnProperty('workspaces'); this.scripts = this.json.scripts || {}; } @@ -8120,7 +8247,7 @@ function normalizePath(path) { } /***/ }), -/* 54 */ +/* 55 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -8128,9 +8255,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__(55); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); /* 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__(83); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(98); /* 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 @@ -8152,8 +8279,9 @@ __webpack_require__.r(__webpack_exports__); */ -function readPackageJson(dir) { - return read_pkg__WEBPACK_IMPORTED_MODULE_0___default()(dir, { +function readPackageJson(cwd) { + return read_pkg__WEBPACK_IMPORTED_MODULE_0___default()({ + cwd, normalize: false }); } @@ -8163,112 +8291,70 @@ function writePackageJson(path, json) { const isLinkDependency = depVersion => depVersion.startsWith('link:'); /***/ }), -/* 55 */ +/* 56 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const {promisify} = __webpack_require__(29); +const fs = __webpack_require__(23); const path = __webpack_require__(16); -const loadJsonFile = __webpack_require__(56); -const pathType = __webpack_require__(63); - -module.exports = (fp, opts) => { - if (typeof fp !== 'string') { - opts = fp; - fp = '.'; - } - - opts = opts || {}; - - return pathType.dir(fp) - .then(isDir => { - if (isDir) { - fp = path.join(fp, 'package.json'); - } - - return loadJsonFile(fp); - }) - .then(x => { - if (opts.normalize !== false) { - __webpack_require__(65)(x); - } +const parseJson = __webpack_require__(57); - return x; - }); -}; - -module.exports.sync = (fp, opts) => { - if (typeof fp !== 'string') { - opts = fp; - fp = '.'; - } +const readFileAsync = promisify(fs.readFile); - opts = opts || {}; - fp = pathType.dirSync(fp) ? path.join(fp, 'package.json') : fp; +module.exports = async options => { + options = { + cwd: process.cwd(), + normalize: true, + ...options + }; - const x = loadJsonFile.sync(fp); + const filePath = path.resolve(options.cwd, 'package.json'); + const json = parseJson(await readFileAsync(filePath, 'utf8')); - if (opts.normalize !== false) { - __webpack_require__(65)(x); + if (options.normalize) { + __webpack_require__(73)(json); } - return x; + return json; }; +module.exports.sync = options => { + options = { + cwd: process.cwd(), + normalize: true, + ...options + }; -/***/ }), -/* 56 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const path = __webpack_require__(16); -const fs = __webpack_require__(22); -const stripBom = __webpack_require__(57); -const parseJson = __webpack_require__(58); -const pify = __webpack_require__(62); - -const parse = (data, fp) => parseJson(stripBom(data), path.relative('.', fp)); - -module.exports = fp => pify(fs.readFile)(fp, 'utf8').then(data => parse(data, fp)); -module.exports.sync = fp => parse(fs.readFileSync(fp, 'utf8'), fp); - - -/***/ }), -/* 57 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -module.exports = x => { - if (typeof x !== 'string') { - throw new TypeError('Expected a string, got ' + typeof x); - } + const filePath = path.resolve(options.cwd, 'package.json'); + const json = parseJson(fs.readFileSync(filePath, 'utf8')); - // 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); + if (options.normalize) { + __webpack_require__(73)(json); } - return x; + return json; }; /***/ }), -/* 58 */ +/* 57 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const errorEx = __webpack_require__(59); -const fallback = __webpack_require__(61); +const errorEx = __webpack_require__(58); +const fallback = __webpack_require__(60); +const {default: LinesAndColumns} = __webpack_require__(61); +const {codeFrameColumns} = __webpack_require__(62); const JSONError = errorEx('JSONError', { - fileName: errorEx.append('in %s') + fileName: errorEx.append('in %s'), + codeFrame: errorEx.append('\n\n%s\n') }); -module.exports = (input, reviver, filename) => { +module.exports = (string, reviver, filename) => { if (typeof reviver === 'string') { filename = reviver; reviver = null; @@ -8276,34 +8362,48 @@ module.exports = (input, reviver, filename) => { try { try { - return JSON.parse(input, reviver); - } catch (err) { - fallback(input, reviver); - - throw err; + return JSON.parse(string, reviver); + } catch (error) { + fallback(string, reviver); + throw error; } - } catch (err) { - err.message = err.message.replace(/\n/g, ''); + } catch (error) { + error.message = error.message.replace(/\n/g, ''); + const indexMatch = error.message.match(/in JSON at position (\d+) while parsing near/); - const jsonErr = new JSONError(err); + const jsonError = new JSONError(error); if (filename) { - jsonErr.fileName = filename; + jsonError.fileName = filename; + } + + if (indexMatch && indexMatch.length > 0) { + const lines = new LinesAndColumns(string); + const index = Number(indexMatch[1]); + const location = lines.locationForIndex(index); + + const codeFrame = codeFrameColumns( + string, + {start: {line: location.line + 1, column: location.column + 1}}, + {highlightCode: true} + ); + + jsonError.codeFrame = codeFrame; } - throw jsonErr; + throw jsonError; } }; /***/ }), -/* 59 */ +/* 58 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var isArrayish = __webpack_require__(60); +var isArrayish = __webpack_require__(59); var errorEx = function errorEx(name, properties) { if (!name || name.constructor !== String) { @@ -8436,7 +8536,7 @@ module.exports = errorEx; /***/ }), -/* 60 */ +/* 59 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8453,7 +8553,7 @@ module.exports = function isArrayish(obj) { /***/ }), -/* 61 */ +/* 60 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8491,6 +8591,70 @@ function parseJson (txt, reviver, context) { } +/***/ }), +/* 61 */ +/***/ (function(__webpack_module__, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +var LF = '\n'; +var CR = '\r'; +var LinesAndColumns = (function () { + function LinesAndColumns(string) { + this.string = string; + var offsets = [0]; + for (var offset = 0; offset < string.length;) { + switch (string[offset]) { + case LF: + offset += LF.length; + offsets.push(offset); + break; + case CR: + offset += CR.length; + if (string[offset] === LF) { + offset += LF.length; + } + offsets.push(offset); + break; + default: + offset++; + break; + } + } + this.offsets = offsets; + } + LinesAndColumns.prototype.locationForIndex = function (index) { + if (index < 0 || index > this.string.length) { + return null; + } + var line = 0; + var offsets = this.offsets; + while (offsets[line + 1] <= index) { + line++; + } + var column = index - offsets[line]; + return { line: line, column: column }; + }; + LinesAndColumns.prototype.indexForLocation = function (location) { + var line = location.line, column = location.column; + if (line < 0 || line >= this.offsets.length) { + return null; + } + if (column < 0 || column > this.lengthOfLine(line)) { + return null; + } + return this.offsets[line] + column; + }; + LinesAndColumns.prototype.lengthOfLine = function (line) { + var offset = this.offsets[line]; + var nextOffset = line === this.offsets.length - 1 ? this.string.length : this.offsets[line + 1]; + return nextOffset - offset; + }; + return LinesAndColumns; +}()); +/* harmony default export */ __webpack_exports__["default"] = (LinesAndColumns); + + /***/ }), /* 62 */ /***/ (function(module, exports, __webpack_require__) { @@ -8498,2719 +8662,4018 @@ function parseJson (txt, reviver, context) { "use strict"; -const processFn = (fn, opts) => function () { - const P = opts.promiseModule; - const args = new Array(arguments.length); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.codeFrameColumns = codeFrameColumns; +exports.default = _default; - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } +function _highlight() { + const data = _interopRequireWildcard(__webpack_require__(63)); - return new P((resolve, reject) => { - if (opts.errorFirst) { - args.push(function (err, result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); + _highlight = function () { + return data; + }; - for (let i = 1; i < arguments.length; i++) { - results[i - 1] = arguments[i]; - } + return data; +} - if (err) { - results.unshift(err); - reject(results); - } else { - resolve(results); - } - } else if (err) { - reject(err); - } else { - resolve(result); - } - }); - } else { - args.push(function (result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); +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)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } - for (let i = 0; i < arguments.length; i++) { - results[i] = arguments[i]; - } +let deprecationWarningShown = false; - resolve(results); - } else { - resolve(result); - } - }); - } +function getDefs(chalk) { + return { + gutter: chalk.grey, + marker: chalk.red.bold, + message: chalk.red.bold + }; +} - fn.apply(this, args); - }); -}; +const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; -module.exports = (obj, opts) => { - opts = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, opts); +function getMarkerLines(loc, source, opts) { + const startLoc = Object.assign({ + column: 0, + line: -1 + }, loc.start); + const endLoc = Object.assign({}, startLoc, loc.end); + const { + linesAbove = 2, + linesBelow = 3 + } = opts || {}; + const startLine = startLoc.line; + const startColumn = startLoc.column; + const endLine = endLoc.line; + const endColumn = endLoc.column; + let start = Math.max(startLine - (linesAbove + 1), 0); + let end = Math.min(source.length, endLine + linesBelow); - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return opts.include ? opts.include.some(match) : !opts.exclude.some(match); - }; + if (startLine === -1) { + start = 0; + } - let ret; - if (typeof obj === 'function') { - ret = function () { - if (opts.excludeMain) { - return obj.apply(this, arguments); - } + if (endLine === -1) { + end = source.length; + } - return processFn(obj, opts).apply(this, arguments); - }; - } else { - ret = Object.create(Object.getPrototypeOf(obj)); - } + const lineDiff = endLine - startLine; + const markerLines = {}; - for (const key in obj) { // eslint-disable-line guard-for-in - const x = obj[key]; - ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; - } + if (lineDiff) { + for (let i = 0; i <= lineDiff; i++) { + const lineNumber = i + startLine; - return ret; -}; + if (!startColumn) { + markerLines[lineNumber] = true; + } else if (i === 0) { + const sourceLength = source[lineNumber - 1].length; + markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1]; + } else if (i === lineDiff) { + markerLines[lineNumber] = [0, endColumn]; + } else { + const sourceLength = source[lineNumber - i].length; + markerLines[lineNumber] = [0, sourceLength]; + } + } + } else { + if (startColumn === endColumn) { + if (startColumn) { + markerLines[startLine] = [startColumn, 0]; + } else { + markerLines[startLine] = true; + } + } else { + markerLines[startLine] = [startColumn, endColumn - startColumn]; + } + } + return { + start, + end, + markerLines + }; +} -/***/ }), -/* 63 */ -/***/ (function(module, exports, __webpack_require__) { +function codeFrameColumns(rawLines, loc, opts = {}) { + const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight().shouldHighlight)(opts); + const chalk = (0, _highlight().getChalk)(opts); + const defs = getDefs(chalk); -"use strict"; + const maybeHighlight = (chalkFn, string) => { + return highlighted ? chalkFn(string) : string; + }; -const fs = __webpack_require__(23); -const pify = __webpack_require__(64); + const lines = rawLines.split(NEWLINE); + const { + start, + end, + markerLines + } = getMarkerLines(loc, lines, opts); + const hasColumns = loc.start && typeof loc.start.column === "number"; + const numberMaxWidth = String(end).length; + const highlightedLines = highlighted ? (0, _highlight().default)(rawLines, opts) : rawLines; + let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => { + const number = start + 1 + index; + const paddedNumber = ` ${number}`.slice(-numberMaxWidth); + const gutter = ` ${paddedNumber} | `; + const hasMarker = markerLines[number]; + const lastMarkerLine = !markerLines[number + 1]; -function type(fn, fn2, fp) { - if (typeof fp !== 'string') { - return Promise.reject(new TypeError(`Expected a string, got ${typeof fp}`)); - } + if (hasMarker) { + let markerLine = ""; - return pify(fs[fn])(fp) - .then(stats => stats[fn2]()) - .catch(err => { - if (err.code === 'ENOENT') { - return false; - } + if (Array.isArray(hasMarker)) { + const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " "); + const numberOfMarkers = hasMarker[1] || 1; + markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), markerSpacing, maybeHighlight(defs.marker, "^").repeat(numberOfMarkers)].join(""); - throw err; - }); -} + if (lastMarkerLine && opts.message) { + markerLine += " " + maybeHighlight(defs.message, opts.message); + } + } -function typeSync(fn, fn2, fp) { - if (typeof fp !== 'string') { - throw new TypeError(`Expected a string, got ${typeof fp}`); - } + return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line, markerLine].join(""); + } else { + return ` ${maybeHighlight(defs.gutter, gutter)}${line}`; + } + }).join("\n"); - try { - return fs[fn](fp)[fn2](); - } catch (err) { - if (err.code === 'ENOENT') { - return false; - } + if (opts.message && !hasColumns) { + frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`; + } - throw err; - } + if (highlighted) { + return chalk.reset(frame); + } else { + return frame; + } } -exports.file = type.bind(null, 'stat', 'isFile'); -exports.dir = type.bind(null, 'stat', 'isDirectory'); -exports.symlink = type.bind(null, 'lstat', 'isSymbolicLink'); -exports.fileSync = typeSync.bind(null, 'statSync', 'isFile'); -exports.dirSync = typeSync.bind(null, 'statSync', 'isDirectory'); -exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); +function _default(rawLines, lineNumber, colNumber, opts = {}) { + if (!deprecationWarningShown) { + deprecationWarningShown = true; + const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`."; + + if (process.emitWarning) { + process.emitWarning(message, "DeprecationWarning"); + } else { + const deprecationError = new Error(message); + deprecationError.name = "DeprecationWarning"; + console.warn(new Error(message)); + } + } + colNumber = Math.max(colNumber, 0); + const location = { + start: { + column: colNumber, + line: lineNumber + } + }; + return codeFrameColumns(rawLines, location, opts); +} /***/ }), -/* 64 */ +/* 63 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const processFn = (fn, opts) => function () { - const P = opts.promiseModule; - const args = new Array(arguments.length); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.shouldHighlight = shouldHighlight; +exports.getChalk = getChalk; +exports.default = highlight; - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } +function _jsTokens() { + const data = _interopRequireWildcard(__webpack_require__(64)); - return new P((resolve, reject) => { - if (opts.errorFirst) { - args.push(function (err, result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); + _jsTokens = function () { + return data; + }; - for (let i = 1; i < arguments.length; i++) { - results[i - 1] = arguments[i]; - } + return data; +} - if (err) { - results.unshift(err); - reject(results); - } else { - resolve(results); - } - } else if (err) { - reject(err); - } else { - resolve(result); - } - }); - } else { - args.push(function (result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); +function _esutils() { + const data = _interopRequireDefault(__webpack_require__(65)); - for (let i = 0; i < arguments.length; i++) { - results[i] = arguments[i]; - } + _esutils = function () { + return data; + }; - resolve(results); - } else { - resolve(result); - } - }); - } + return data; +} - fn.apply(this, args); - }); -}; +function _chalk() { + const data = _interopRequireDefault(__webpack_require__(69)); -module.exports = (obj, opts) => { - opts = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, opts); + _chalk = function () { + return data; + }; - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return opts.include ? opts.include.some(match) : !opts.exclude.some(match); - }; + return data; +} - let ret; - if (typeof obj === 'function') { - ret = function () { - if (opts.excludeMain) { - return obj.apply(this, arguments); - } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - return processFn(obj, opts).apply(this, arguments); - }; - } else { - ret = Object.create(Object.getPrototypeOf(obj)); - } +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)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } - for (const key in obj) { // eslint-disable-line guard-for-in - const x = obj[key]; - ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; - } +function getDefs(chalk) { + return { + keyword: chalk.cyan, + capitalized: chalk.yellow, + jsx_tag: chalk.yellow, + punctuator: chalk.yellow, + number: chalk.magenta, + string: chalk.green, + regex: chalk.magenta, + comment: chalk.grey, + invalid: chalk.white.bgRed.bold + }; +} - return ret; -}; +const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; +const JSX_TAG = /^[a-z][\w-]*$/i; +const BRACKET = /^[()[\]{}]$/; +function getTokenType(match) { + const [offset, text] = match.slice(-2); + const token = (0, _jsTokens().matchToToken)(match); -/***/ }), -/* 65 */ -/***/ (function(module, exports, __webpack_require__) { + if (token.type === "name") { + if (_esutils().default.keyword.isReservedWordES6(token.value)) { + return "keyword"; + } -module.exports = normalize + if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == " ucFirst(name) + "Field" -// thingsToFix = (ucFirst(name) + "Field" for name in fieldsToFix) -thingsToFix = thingsToFix.concat(otherThingsToFix) + return token.type; +} -function normalize (data, warn, strict) { - if(warn === true) warn = null, strict = true - if(!strict) strict = false - if(!warn || data.private) warn = function(msg) { /* noop */ } +function highlightTokens(defs, text) { + return text.replace(_jsTokens().default, function (...args) { + const type = getTokenType(args); + const colorize = defs[type]; - if (data.scripts && - data.scripts.install === "node-gyp rebuild" && - !data.scripts.preinstall) { - data.gypfile = true + if (colorize) { + return args[0].split(NEWLINE).map(str => colorize(str)).join("\n"); + } else { + return args[0]; + } + }); +} + +function shouldHighlight(options) { + return _chalk().default.supportsColor || options.forceColor; +} + +function getChalk(options) { + let chalk = _chalk().default; + + if (options.forceColor) { + chalk = new (_chalk().default.constructor)({ + enabled: true, + level: 1 + }); } - fixer.warn = function() { warn(makeWarning.apply(null, arguments)) } - thingsToFix.forEach(function(thingName) { - fixer["fix" + ucFirst(thingName)](data, strict) - }) - data._id = data.name + "@" + data.version + + return chalk; } -function ucFirst (string) { - return string.charAt(0).toUpperCase() + string.slice(1); +function highlight(code, options = {}) { + if (shouldHighlight(options)) { + const chalk = getChalk(options); + const defs = getDefs(chalk); + return highlightTokens(defs, code); + } else { + return code; + } +} + +/***/ }), +/* 64 */ +/***/ (function(module, exports) { + +// Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell +// License: MIT. (See LICENSE.) + +Object.defineProperty(exports, "__esModule", { + value: true +}) + +// This regex comes from regex.coffee, and is inserted here by generate-index.js +// (run `npm run build`). +exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g + +exports.matchToToken = function(match) { + var token = {type: "invalid", value: match[0], closed: undefined} + if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4]) + else if (match[ 5]) token.type = "comment" + else if (match[ 6]) token.type = "comment", token.closed = !!match[7] + else if (match[ 8]) token.type = "regex" + else if (match[ 9]) token.type = "number" + else if (match[10]) token.type = "name" + else if (match[11]) token.type = "punctuator" + else if (match[12]) token.type = "whitespace" + return token } /***/ }), -/* 66 */ +/* 65 */ /***/ (function(module, exports, __webpack_require__) { -var semver = __webpack_require__(67) -var validateLicense = __webpack_require__(68); -var hostedGitInfo = __webpack_require__(73) -var isBuiltinModule = __webpack_require__(77) -var depTypes = ["dependencies","devDependencies","optionalDependencies"] -var extractDescription = __webpack_require__(79) -var url = __webpack_require__(74) -var typos = __webpack_require__(80) +/* + Copyright (C) 2013 Yusuke Suzuki + + 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. + + 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 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 fixer = module.exports = { - // default warning function - warn: function() {}, - fixRepositoryField: function(data) { - if (data.repositories) { - this.warn("repositories"); - data.repository = data.repositories[0] +(function () { + 'use strict'; + + exports.ast = __webpack_require__(66); + exports.code = __webpack_require__(67); + exports.keyword = __webpack_require__(68); +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ + + +/***/ }), +/* 66 */ +/***/ (function(module, exports) { + +/* + Copyright (C) 2013 Yusuke Suzuki + + 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. + + 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 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. +*/ + +(function () { + 'use strict'; + + function isExpression(node) { + if (node == null) { return false; } + switch (node.type) { + case 'ArrayExpression': + case 'AssignmentExpression': + case 'BinaryExpression': + case 'CallExpression': + case 'ConditionalExpression': + case 'FunctionExpression': + case 'Identifier': + case 'Literal': + case 'LogicalExpression': + case 'MemberExpression': + case 'NewExpression': + case 'ObjectExpression': + case 'SequenceExpression': + case 'ThisExpression': + case 'UnaryExpression': + case 'UpdateExpression': + return true; + } + return false; } - if (!data.repository) return this.warn("missingRepository") - if (typeof data.repository === "string") { - data.repository = { - type: "git", - url: data.repository - } + + function isIterationStatement(node) { + if (node == null) { return false; } + switch (node.type) { + case 'DoWhileStatement': + case 'ForInStatement': + case 'ForStatement': + case 'WhileStatement': + return true; + } + return false; } - var r = data.repository.url || "" - if (r) { - var hosted = hostedGitInfo.fromUrl(r) - if (hosted) { - r = data.repository.url - = hosted.getDefaultRepresentation() == "shortcut" ? hosted.https() : hosted.toString() - } + + function isStatement(node) { + if (node == null) { return false; } + switch (node.type) { + case 'BlockStatement': + case 'BreakStatement': + case 'ContinueStatement': + case 'DebuggerStatement': + case 'DoWhileStatement': + case 'EmptyStatement': + case 'ExpressionStatement': + case 'ForInStatement': + case 'ForStatement': + case 'IfStatement': + case 'LabeledStatement': + case 'ReturnStatement': + case 'SwitchStatement': + case 'ThrowStatement': + case 'TryStatement': + case 'VariableDeclaration': + case 'WhileStatement': + case 'WithStatement': + return true; + } + return false; } - if (r.match(/github.com\/[^\/]+\/[^\/]+\.git\.git$/)) { - this.warn("brokenGitUrl", r) + function isSourceElement(node) { + return isStatement(node) || node != null && node.type === 'FunctionDeclaration'; } - } -, fixTypos: function(data) { - Object.keys(typos.topLevel).forEach(function (d) { - if (data.hasOwnProperty(d)) { - this.warn("typo", d, typos.topLevel[d]) - } - }, this) - } + function trailingStatement(node) { + switch (node.type) { + case 'IfStatement': + if (node.alternate != null) { + return node.alternate; + } + return node.consequent; -, fixScriptsField: function(data) { - if (!data.scripts) return - if (typeof data.scripts !== "object") { - this.warn("nonObjectScripts") - delete data.scripts - return - } - Object.keys(data.scripts).forEach(function (k) { - if (typeof data.scripts[k] !== "string") { - this.warn("nonStringScript") - delete data.scripts[k] - } else if (typos.script[k] && !data.scripts[typos.script[k]]) { - this.warn("typo", k, typos.script[k], "scripts") - } - }, this) - } - -, fixFilesField: function(data) { - var files = data.files - if (files && !Array.isArray(files)) { - this.warn("nonArrayFiles") - delete data.files - } else if (data.files) { - data.files = data.files.filter(function(file) { - if (!file || typeof file !== "string") { - this.warn("invalidFilename", file) - return false - } else { - return true + case 'LabeledStatement': + case 'ForStatement': + case 'ForInStatement': + case 'WhileStatement': + case 'WithStatement': + return node.body; } - }, this) + return null; } - } -, fixBinField: function(data) { - if (!data.bin) return; - if (typeof data.bin === "string") { - var b = {} - var match - if (match = data.name.match(/^@[^/]+[/](.*)$/)) { - b[match[1]] = data.bin - } else { - b[data.name] = data.bin - } - data.bin = b - } - } + function isProblematicIfStatement(node) { + var current; -, fixManField: function(data) { - if (!data.man) return; - if (typeof data.man === "string") { - data.man = [ data.man ] - } - } -, fixBundleDependenciesField: function(data) { - var bdd = "bundledDependencies" - var bd = "bundleDependencies" - if (data[bdd] && !data[bd]) { - data[bd] = data[bdd] - delete data[bdd] - } - if (data[bd] && !Array.isArray(data[bd])) { - this.warn("nonArrayBundleDependencies") - delete data[bd] - } else if (data[bd]) { - data[bd] = data[bd].filter(function(bd) { - if (!bd || typeof bd !== 'string') { - this.warn("nonStringBundleDependency", bd) - return false - } else { - if (!data.dependencies) { - data.dependencies = {} - } - if (!data.dependencies.hasOwnProperty(bd)) { - this.warn("nonDependencyBundleDependency", bd) - data.dependencies[bd] = "*" - } - return true + if (node.type !== 'IfStatement') { + return false; } - }, this) + if (node.alternate == null) { + return false; + } + current = node.consequent; + do { + if (current.type === 'IfStatement') { + if (current.alternate == null) { + return true; + } + } + current = trailingStatement(current); + } while (current); + + return false; } - } -, fixDependencies: function(data, strict) { - var loose = !strict - objectifyDeps(data, this.warn) - addOptionalDepsToDeps(data, this.warn) - this.fixBundleDependenciesField(data) + module.exports = { + isExpression: isExpression, + isStatement: isStatement, + isIterationStatement: isIterationStatement, + isSourceElement: isSourceElement, + isProblematicIfStatement: isProblematicIfStatement, - ;['dependencies','devDependencies'].forEach(function(deps) { - if (!(deps in data)) return - if (!data[deps] || typeof data[deps] !== "object") { - this.warn("nonObjectDependencies", deps) - delete data[deps] - return - } - Object.keys(data[deps]).forEach(function (d) { - var r = data[deps][d] - if (typeof r !== 'string') { - this.warn("nonStringDependency", d, JSON.stringify(r)) - delete data[deps][d] - } - var hosted = hostedGitInfo.fromUrl(data[deps][d]) - if (hosted) data[deps][d] = hosted.toString() - }, this) - }, this) - } + trailingStatement: trailingStatement + }; +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ -, fixModulesField: function (data) { - if (data.modules) { - this.warn("deprecatedModules") - delete data.modules - } - } -, fixKeywordsField: function (data) { - if (typeof data.keywords === "string") { - data.keywords = data.keywords.split(/,\s+/) - } - if (data.keywords && !Array.isArray(data.keywords)) { - delete data.keywords - this.warn("nonArrayKeywords") - } else if (data.keywords) { - data.keywords = data.keywords.filter(function(kw) { - if (typeof kw !== "string" || !kw) { - this.warn("nonStringKeyword"); - return false - } else { - return true - } - }, this) +/***/ }), +/* 67 */ +/***/ (function(module, exports) { + +/* + Copyright (C) 2013-2014 Yusuke Suzuki + Copyright (C) 2014 Ivan Nikulin + + 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. + + 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 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. +*/ + +(function () { + 'use strict'; + + var ES6Regex, ES5Regex, NON_ASCII_WHITESPACES, IDENTIFIER_START, IDENTIFIER_PART, ch; + + // See `tools/generate-identifier-regex.js`. + ES5Regex = { + // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierStart: + NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/, + // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierPart: + NonAsciiIdentifierPart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/ + }; + + ES6Regex = { + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart: + NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/, + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart: + NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ + }; + + function isDecimalDigit(ch) { + return 0x30 <= ch && ch <= 0x39; // 0..9 } - } -, fixVersionField: function(data, strict) { - // allow "loose" semver 1.0 versions in non-strict mode - // enforce strict semver 2.0 compliance in strict mode - var loose = !strict - if (!data.version) { - data.version = "" - return true + function isHexDigit(ch) { + return 0x30 <= ch && ch <= 0x39 || // 0..9 + 0x61 <= ch && ch <= 0x66 || // a..f + 0x41 <= ch && ch <= 0x46; // A..F } - if (!semver.valid(data.version, loose)) { - throw new Error('Invalid version: "'+ data.version + '"') + + function isOctalDigit(ch) { + return ch >= 0x30 && ch <= 0x37; // 0..7 } - data.version = semver.clean(data.version, loose) - return true - } -, fixPeople: function(data) { - modifyPeople(data, unParsePerson) - modifyPeople(data, parsePerson) - } + // 7.2 White Space -, fixNameField: function(data, options) { - if (typeof options === "boolean") options = {strict: options} - else if (typeof options === "undefined") options = {} - var strict = options.strict - if (!data.name && !strict) { - data.name = "" - return - } - if (typeof data.name !== "string") { - throw new Error("name field must be a string.") + NON_ASCII_WHITESPACES = [ + 0x1680, 0x180E, + 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, + 0x202F, 0x205F, + 0x3000, + 0xFEFF + ]; + + function isWhiteSpace(ch) { + return ch === 0x20 || ch === 0x09 || ch === 0x0B || ch === 0x0C || ch === 0xA0 || + ch >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(ch) >= 0; } - if (!strict) - data.name = data.name.trim() - ensureValidName(data.name, strict, options.allowLegacyCase) - if (isBuiltinModule(data.name)) - this.warn("conflictingName", data.name) - } + // 7.3 Line Terminators -, fixDescriptionField: function (data) { - if (data.description && typeof data.description !== 'string') { - this.warn("nonStringDescription") - delete data.description + function isLineTerminator(ch) { + return ch === 0x0A || ch === 0x0D || ch === 0x2028 || ch === 0x2029; } - if (data.readme && !data.description) - data.description = extractDescription(data.readme) - if(data.description === undefined) delete data.description; - if (!data.description) this.warn("missingDescription") - } -, fixReadmeField: function (data) { - if (!data.readme) { - this.warn("missingReadme") - data.readme = "ERROR: No README data found!" - } - } + // 7.6 Identifier Names and Identifiers -, fixBugsField: function(data) { - if (!data.bugs && data.repository && data.repository.url) { - var hosted = hostedGitInfo.fromUrl(data.repository.url) - if(hosted && hosted.bugs()) { - data.bugs = {url: hosted.bugs()} - } + function fromCodePoint(cp) { + if (cp <= 0xFFFF) { return String.fromCharCode(cp); } + var cu1 = String.fromCharCode(Math.floor((cp - 0x10000) / 0x400) + 0xD800); + var cu2 = String.fromCharCode(((cp - 0x10000) % 0x400) + 0xDC00); + return cu1 + cu2; } - else if(data.bugs) { - var emailRe = /^.+@.*\..+$/ - if(typeof data.bugs == "string") { - if(emailRe.test(data.bugs)) - data.bugs = {email:data.bugs} - else if(url.parse(data.bugs).protocol) - data.bugs = {url: data.bugs} - else - this.warn("nonEmailUrlBugsString") - } - else { - bugsTypos(data.bugs, this.warn) - var oldBugs = data.bugs - data.bugs = {} - if(oldBugs.url) { - if(typeof(oldBugs.url) == "string" && url.parse(oldBugs.url).protocol) - data.bugs.url = oldBugs.url - else - this.warn("nonUrlBugsUrlField") - } - if(oldBugs.email) { - if(typeof(oldBugs.email) == "string" && emailRe.test(oldBugs.email)) - data.bugs.email = oldBugs.email - else - this.warn("nonEmailBugsEmailField") - } - } - if(!data.bugs.email && !data.bugs.url) { - delete data.bugs - this.warn("emptyNormalizedBugs") - } + + IDENTIFIER_START = new Array(0x80); + for(ch = 0; ch < 0x80; ++ch) { + IDENTIFIER_START[ch] = + ch >= 0x61 && ch <= 0x7A || // a..z + ch >= 0x41 && ch <= 0x5A || // A..Z + ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore) } - } -, fixHomepageField: function(data) { - if (!data.homepage && data.repository && data.repository.url) { - var hosted = hostedGitInfo.fromUrl(data.repository.url) - if (hosted && hosted.docs()) data.homepage = hosted.docs() + IDENTIFIER_PART = new Array(0x80); + for(ch = 0; ch < 0x80; ++ch) { + IDENTIFIER_PART[ch] = + ch >= 0x61 && ch <= 0x7A || // a..z + ch >= 0x41 && ch <= 0x5A || // A..Z + ch >= 0x30 && ch <= 0x39 || // 0..9 + ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore) } - if (!data.homepage) return - if(typeof data.homepage !== "string") { - this.warn("nonUrlHomepage") - return delete data.homepage + function isIdentifierStartES5(ch) { + return ch < 0x80 ? IDENTIFIER_START[ch] : ES5Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)); } - if(!url.parse(data.homepage).protocol) { - data.homepage = "http://" + data.homepage + + function isIdentifierPartES5(ch) { + return ch < 0x80 ? IDENTIFIER_PART[ch] : ES5Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)); } - } -, fixLicenseField: function(data) { - if (!data.license) { - return this.warn("missingLicense") - } else{ - if ( - typeof(data.license) !== 'string' || - data.license.length < 1 - ) { - this.warn("invalidLicense") - } else { - if (!validateLicense(data.license).validForNewPackages) - this.warn("invalidLicense") - } + function isIdentifierStartES6(ch) { + return ch < 0x80 ? IDENTIFIER_START[ch] : ES6Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)); } - } -} -function isValidScopedPackageName(spec) { - if (spec.charAt(0) !== '@') return false + function isIdentifierPartES6(ch) { + return ch < 0x80 ? IDENTIFIER_PART[ch] : ES6Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)); + } - var rest = spec.slice(1).split('/') - if (rest.length !== 2) return false + module.exports = { + isDecimalDigit: isDecimalDigit, + isHexDigit: isHexDigit, + isOctalDigit: isOctalDigit, + isWhiteSpace: isWhiteSpace, + isLineTerminator: isLineTerminator, + isIdentifierStartES5: isIdentifierStartES5, + isIdentifierPartES5: isIdentifierPartES5, + isIdentifierStartES6: isIdentifierStartES6, + isIdentifierPartES6: isIdentifierPartES6 + }; +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ - return rest[0] && rest[1] && - rest[0] === encodeURIComponent(rest[0]) && - rest[1] === encodeURIComponent(rest[1]) -} -function isCorrectlyEncodedName(spec) { - return !spec.match(/[\/@\s\+%:]/) && - spec === encodeURIComponent(spec) -} +/***/ }), +/* 68 */ +/***/ (function(module, exports, __webpack_require__) { -function ensureValidName (name, strict, allowLegacyCase) { - if (name.charAt(0) === "." || - !(isValidScopedPackageName(name) || isCorrectlyEncodedName(name)) || - (strict && (!allowLegacyCase) && name !== name.toLowerCase()) || - name.toLowerCase() === "node_modules" || - name.toLowerCase() === "favicon.ico") { - throw new Error("Invalid name: " + JSON.stringify(name)) - } -} +/* + Copyright (C) 2013 Yusuke Suzuki + + 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. + + 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 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. +*/ -function modifyPeople (data, fn) { - if (data.author) data.author = fn(data.author) - ;["maintainers", "contributors"].forEach(function (set) { - if (!Array.isArray(data[set])) return; - data[set] = data[set].map(fn) - }) - return data -} +(function () { + 'use strict'; + + var code = __webpack_require__(67); + + function isStrictModeReservedWordES6(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'let': + return true; + default: + return false; + } + } -function unParsePerson (person) { - if (typeof person === "string") return person - var name = person.name || "" - var u = person.url || person.web - var url = u ? (" ("+u+")") : "" - var e = person.email || person.mail - var email = e ? (" <"+e+">") : "" - return name+email+url -} + function isKeywordES5(id, strict) { + // yield should not be treated as keyword under non-strict mode. + if (!strict && id === 'yield') { + return false; + } + return isKeywordES6(id, strict); + } -function parsePerson (person) { - if (typeof person !== "string") return person - var name = person.match(/^([^\(<]+)/) - var url = person.match(/\(([^\)]+)\)/) - var email = person.match(/<([^>]+)>/) - var obj = {} - if (name && name[0].trim()) obj.name = name[0].trim() - if (email) obj.email = email[1]; - if (url) obj.url = url[1]; - return obj -} + function isKeywordES6(id, strict) { + if (strict && isStrictModeReservedWordES6(id)) { + return true; + } -function addOptionalDepsToDeps (data, warn) { - var o = data.optionalDependencies - if (!o) return; - var d = data.dependencies || {} - Object.keys(o).forEach(function (k) { - d[k] = o[k] - }) - data.dependencies = d -} + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } -function depObjectify (deps, type, warn) { - if (!deps) return {} - if (typeof deps === "string") { - deps = deps.trim().split(/[\n\r\s\t ,]+/) - } - if (!Array.isArray(deps)) return deps - warn("deprecatedArrayDependencies", type) - var o = {} - deps.filter(function (d) { - return typeof d === "string" - }).forEach(function(d) { - d = d.trim().split(/(:?[@\s><=])/) - var dn = d.shift() - var dv = d.join("") - dv = dv.trim() - dv = dv.replace(/^@/, "") - o[dn] = dv - }) - return o -} + function isReservedWordES5(id, strict) { + return id === 'null' || id === 'true' || id === 'false' || isKeywordES5(id, strict); + } -function objectifyDeps (data, warn) { - depTypes.forEach(function (type) { - if (!data[type]) return; - data[type] = depObjectify(data[type], type, warn) - }) -} + function isReservedWordES6(id, strict) { + return id === 'null' || id === 'true' || id === 'false' || isKeywordES6(id, strict); + } -function bugsTypos(bugs, warn) { - if (!bugs) return - Object.keys(bugs).forEach(function (k) { - if (typos.bugs[k]) { - warn("typo", k, typos.bugs[k], "bugs") - bugs[typos.bugs[k]] = bugs[k] - delete bugs[k] + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; } - }) -} + function isIdentifierNameES5(id) { + var i, iz, ch; -/***/ }), -/* 67 */ -/***/ (function(module, exports) { + if (id.length === 0) { return false; } -exports = module.exports = SemVer; + ch = id.charCodeAt(0); + if (!code.isIdentifierStartES5(ch)) { + return false; + } -// The debug function is excluded entirely from the minified version. -/* nomin */ var debug; -/* nomin */ if (typeof process === 'object' && - /* nomin */ process.env && - /* nomin */ process.env.NODE_DEBUG && - /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) - /* nomin */ debug = function() { - /* nomin */ var args = Array.prototype.slice.call(arguments, 0); - /* nomin */ args.unshift('SEMVER'); - /* nomin */ console.log.apply(console, args); - /* nomin */ }; -/* nomin */ else - /* nomin */ debug = function() {}; + for (i = 1, iz = id.length; i < iz; ++i) { + ch = id.charCodeAt(i); + if (!code.isIdentifierPartES5(ch)) { + return false; + } + } + return true; + } -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0'; + function decodeUtf16(lead, trail) { + return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; + } -var MAX_LENGTH = 256; -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + function isIdentifierNameES6(id) { + var i, iz, ch, lowCh, check; -// The actual regexps go on exports.re -var re = exports.re = []; -var src = exports.src = []; -var R = 0; + if (id.length === 0) { return false; } -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. + check = code.isIdentifierStartES6; + for (i = 0, iz = id.length; i < iz; ++i) { + ch = id.charCodeAt(i); + if (0xD800 <= ch && ch <= 0xDBFF) { + ++i; + if (i >= iz) { return false; } + lowCh = id.charCodeAt(i); + if (!(0xDC00 <= lowCh && lowCh <= 0xDFFF)) { + return false; + } + ch = decodeUtf16(ch, lowCh); + } + if (!check(ch)) { + return false; + } + check = code.isIdentifierPartES6; + } + return true; + } -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. + function isIdentifierES5(id, strict) { + return isIdentifierNameES5(id) && !isReservedWordES5(id, strict); + } -var NUMERICIDENTIFIER = R++; -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; -var NUMERICIDENTIFIERLOOSE = R++; -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; + function isIdentifierES6(id, strict) { + return isIdentifierNameES6(id) && !isReservedWordES6(id, strict); + } + module.exports = { + isKeywordES5: isKeywordES5, + isKeywordES6: isKeywordES6, + isReservedWordES5: isReservedWordES5, + isReservedWordES6: isReservedWordES6, + isRestrictedWord: isRestrictedWord, + isIdentifierNameES5: isIdentifierNameES5, + isIdentifierNameES6: isIdentifierNameES6, + isIdentifierES5: isIdentifierES5, + isIdentifierES6: isIdentifierES6 + }; +}()); +/* vim: set sw=4 ts=4 et tw=80 : */ -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. -var NONNUMERICIDENTIFIER = R++; -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; +/***/ }), +/* 69 */ +/***/ (function(module, exports, __webpack_require__) { +"use strict"; -// ## Main Version -// Three dot-separated numeric identifiers. +const escapeStringRegexp = __webpack_require__(3); +const ansiStyles = __webpack_require__(70); +const stdoutColor = __webpack_require__(71).stdout; -var MAINVERSION = R++; -src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')'; +const template = __webpack_require__(72); -var MAINVERSIONLOOSE = R++; -src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; +const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. +// `supportsColor.level` → `ansiStyles.color[name]` mapping +const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; -var PRERELEASEIDENTIFIER = R++; -src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; +// `color-convert` models to exclude from the Chalk API due to conflicts and such +const skipModels = new Set(['gray']); -var PRERELEASEIDENTIFIERLOOSE = R++; -src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; +const styles = Object.create(null); +function applyOptions(obj, options) { + options = options || {}; -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. + // 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; +} -var PRERELEASE = R++; -src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; +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); -var PRERELEASELOOSE = R++; -src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; + chalk.template = function () { + const args = [].slice.call(arguments); + return chalkTag.apply(null, [chalk.template].concat(args)); + }; -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); -var BUILDIDENTIFIER = R++; -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; + chalk.template.constructor = Chalk; -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. + return chalk.template; + } -var BUILD = R++; -src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; + applyOptions(this, options); +} +// Use bright blue on Windows as the normal blue color is illegible +if (isSimpleWindowsTerm) { + ansiStyles.blue.open = '\u001B[94m'; +} -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. +for (const key of Object.keys(ansiStyles)) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. + styles[key] = { + get() { + const codes = ansiStyles[key]; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); + } + }; +} -var FULL = R++; -var FULLPLAIN = 'v?' + src[MAINVERSION] + - src[PRERELEASE] + '?' + - src[BUILD] + '?'; +styles.visible = { + get() { + return build.call(this, this._styles || [], true, 'visible'); + } +}; -src[FULL] = '^' + FULLPLAIN + '$'; +ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); +for (const model of Object.keys(ansiStyles.color.ansi)) { + if (skipModels.has(model)) { + continue; + } -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + - src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?'; + 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); + }; + } + }; +} -var LOOSE = R++; -src[LOOSE] = '^' + LOOSEPLAIN + '$'; +ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); +for (const model of Object.keys(ansiStyles.bgColor.ansi)) { + if (skipModels.has(model)) { + continue; + } -var GTLT = R++; -src[GTLT] = '((?:<|>)?=?)'; + 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); + }; + } + }; +} -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++; -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; -var XRANGEIDENTIFIER = R++; -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; +const proto = Object.defineProperties(() => {}, styles); -var XRANGEPLAIN = R++; -src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:' + src[PRERELEASE] + ')?' + - src[BUILD] + '?' + - ')?)?'; +function build(_styles, _empty, key) { + const builder = function () { + return applyStyle.apply(builder, arguments); + }; -var XRANGEPLAINLOOSE = R++; -src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[PRERELEASELOOSE] + ')?' + - src[BUILD] + '?' + - ')?)?'; + builder._styles = _styles; + builder._empty = _empty; -var XRANGE = R++; -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; -var XRANGELOOSE = R++; -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; + const self = this; -// Tilde ranges. -// Meaning is "reasonably at or greater than" -var LONETILDE = R++; -src[LONETILDE] = '(?:~>?)'; + Object.defineProperty(builder, 'level', { + enumerable: true, + get() { + return self.level; + }, + set(level) { + self.level = level; + } + }); -var TILDETRIM = R++; -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); -var tildeTrimReplace = '$1~'; + Object.defineProperty(builder, 'enabled', { + enumerable: true, + get() { + return self.enabled; + }, + set(enabled) { + self.enabled = enabled; + } + }); -var TILDE = R++; -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; -var TILDELOOSE = R++; -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; + // See below for fix regarding invisible grey/dim combination on Windows + builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; -// Caret ranges. -// Meaning is "at least and backwards compatible with" -var LONECARET = R++; -src[LONECARET] = '(?:\\^)'; + // `__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 -var CARETTRIM = R++; -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); -var caretTrimReplace = '$1^'; + return builder; +} -var CARET = R++; -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; -var CARETLOOSE = R++; -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; +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]); -// A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++; -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; -var COMPARATOR = R++; -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + 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]; + } + } -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++; -src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + if (!this.enabled || this.level <= 0 || !str) { + return this._empty ? '' : str; + } -// this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); -var comparatorTrimReplace = '$1$2$3'; + // 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 = ''; + } + + 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}`); + } -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -var HYPHENRANGE = R++; -src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAIN] + ')' + - '\\s*$'; + // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue + ansiStyles.dim.open = originalDim; -var HYPHENRANGELOOSE = R++; -src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$'; + return str; +} -// Star ranges basically just allow anything at all. -var STAR = R++; -src[STAR] = '(<|>)?=?\\s*\\*'; +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(' '); + } -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]); - if (!re[i]) - re[i] = new RegExp(src[i]); + 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('')); } -exports.parse = parse; -function parse(version, loose) { - if (version instanceof SemVer) - return version; +Object.defineProperties(Chalk.prototype, styles); - if (typeof version !== 'string') - return null; +module.exports = Chalk(); // eslint-disable-line new-cap +module.exports.supportsColor = stdoutColor; +module.exports.default = module.exports; // For TypeScript - if (version.length > MAX_LENGTH) - return null; - var r = loose ? re[LOOSE] : re[FULL]; - if (!r.test(version)) - return null; +/***/ }), +/* 70 */ +/***/ (function(module, exports, __webpack_require__) { - try { - return new SemVer(version, loose); - } catch (er) { - return null; - } -} +"use strict"; +/* WEBPACK VAR INJECTION */(function(module) { +const colorConvert = __webpack_require__(6); -exports.valid = valid; -function valid(version, loose) { - var v = parse(version, loose); - return v ? v.version : null; -} +const wrapAnsi16 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${code + offset}m`; +}; +const wrapAnsi256 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${38 + offset};5;${code}m`; +}; -exports.clean = clean; -function clean(version, loose) { - var s = parse(version.trim().replace(/^[=v]+/, ''), loose); - return s ? s.version : null; -} +const wrapAnsi16m = (fn, offset) => function () { + const rgb = fn.apply(colorConvert, arguments); + return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; +}; -exports.SemVer = SemVer; +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], -function SemVer(version, loose) { - if (version instanceof SemVer) { - if (version.loose === loose) - return version; - else - version = version.version; - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version); - } + // 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], - if (version.length > MAX_LENGTH) - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + // 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] + } + }; - if (!(this instanceof SemVer)) - return new SemVer(version, loose); + // Fix humans + styles.color.grey = styles.color.gray; - debug('SemVer', version, loose); - this.loose = loose; - var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + for (const groupName of Object.keys(styles)) { + const group = styles[groupName]; - if (!m) - throw new TypeError('Invalid Version: ' + version); + for (const styleName of Object.keys(group)) { + const style = group[styleName]; - this.raw = version; + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m` + }; - // these are actually numbers - this.major = +m[1]; - this.minor = +m[2]; - this.patch = +m[3]; + group[styleName] = styles[styleName]; - if (this.major > MAX_SAFE_INTEGER || this.major < 0) - throw new TypeError('Invalid major version') + codes.set(style[0], style[1]); + } - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) - throw new TypeError('Invalid minor version') + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) - throw new TypeError('Invalid patch version') + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); + } - // numberify any prerelease numeric ids - if (!m[4]) - this.prerelease = []; - else - this.prerelease = m[4].split('.').map(function(id) { - if (/^[0-9]+$/.test(id)) { - var num = +id; - if (num >= 0 && num < MAX_SAFE_INTEGER) - return num; - } - return id; - }); + const ansi2ansi = n => n; + const rgb2rgb = (r, g, b) => [r, g, b]; - this.build = m[5] ? m[5].split('.') : []; - this.format(); -} + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; -SemVer.prototype.format = function() { - this.version = this.major + '.' + this.minor + '.' + this.patch; - if (this.prerelease.length) - this.version += '-' + this.prerelease.join('.'); - return this.version; -}; + styles.color.ansi = { + ansi: wrapAnsi16(ansi2ansi, 0) + }; + styles.color.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 0) + }; + styles.color.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 0) + }; -SemVer.prototype.toString = function() { - return this.version; -}; + styles.bgColor.ansi = { + ansi: wrapAnsi16(ansi2ansi, 10) + }; + styles.bgColor.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 10) + }; + styles.bgColor.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 10) + }; -SemVer.prototype.compare = function(other) { - debug('SemVer.compare', this.version, this.loose, other); - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); + for (let key of Object.keys(colorConvert)) { + if (typeof colorConvert[key] !== 'object') { + continue; + } - return this.compareMain(other) || this.comparePre(other); -}; + const suite = colorConvert[key]; -SemVer.prototype.compareMain = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); + if (key === 'ansi16') { + key = 'ansi'; + } - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch); -}; + if ('ansi16' in suite) { + styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0); + styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10); + } -SemVer.prototype.comparePre = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); + if ('ansi256' in suite) { + styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0); + styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10); + } - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) - return -1; - else if (!this.prerelease.length && other.prerelease.length) - return 1; - else if (!this.prerelease.length && !other.prerelease.length) - return 0; + if ('rgb' in suite) { + styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0); + styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10); + } + } - var i = 0; - do { - var a = this.prerelease[i]; - var b = other.prerelease[i]; - debug('prerelease compare', i, a, b); - if (a === undefined && b === undefined) - return 0; - else if (b === undefined) - return 1; - else if (a === undefined) - return -1; - else if (a === b) - continue; - else - return compareIdentifiers(a, b); - } while (++i); -}; + return styles; +} -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function(release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0; - this.patch = 0; - this.minor = 0; - this.major++; - this.inc('pre', identifier); - break; - case 'preminor': - this.prerelease.length = 0; - this.patch = 0; - this.minor++; - this.inc('pre', identifier); - break; - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0; - this.inc('patch', identifier); - this.inc('pre', identifier); - break; - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) - this.inc('patch', identifier); - this.inc('pre', identifier); - break; - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) - this.major++; - this.minor = 0; - this.patch = 0; - this.prerelease = []; - break; - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) - this.minor++; - this.patch = 0; - this.prerelease = []; - break; - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) - this.patch++; - this.prerelease = []; - break; - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) - this.prerelease = [0]; - else { - var i = this.prerelease.length; - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++; - i = -2; - } - } - if (i === -1) // didn't increment anything - this.prerelease.push(0); - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) - this.prerelease = [identifier, 0]; - } else - this.prerelease = [identifier, 0]; - } - break; - - default: - throw new Error('invalid increment argument: ' + release); - } - this.format(); - this.raw = this.version; - return this; -}; - -exports.inc = inc; -function inc(version, release, loose, identifier) { - if (typeof(loose) === 'string') { - identifier = loose; - loose = undefined; - } +// Make the export immutable +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); - try { - return new SemVer(version, loose).inc(release, identifier).version; - } catch (er) { - return null; - } -} +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) -exports.diff = diff; -function diff(version1, version2) { - if (eq(version1, version2)) { - return null; - } else { - var v1 = parse(version1); - var v2 = parse(version2); - if (v1.prerelease.length || v2.prerelease.length) { - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return 'pre'+key; - } - } - } - return 'prerelease'; - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return key; - } - } - } - } -} +/***/ }), +/* 71 */ +/***/ (function(module, exports, __webpack_require__) { -exports.compareIdentifiers = compareIdentifiers; +"use strict"; -var numeric = /^[0-9]+$/; -function compareIdentifiers(a, b) { - var anum = numeric.test(a); - var bnum = numeric.test(b); +const os = __webpack_require__(11); +const hasFlag = __webpack_require__(12); - if (anum && bnum) { - a = +a; - b = +b; - } +const env = process.env; - return (anum && !bnum) ? -1 : - (bnum && !anum) ? 1 : - a < b ? -1 : - a > b ? 1 : - 0; +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + forceColor = false; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = true; } - -exports.rcompareIdentifiers = rcompareIdentifiers; -function rcompareIdentifiers(a, b) { - return compareIdentifiers(b, a); +if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; } -exports.major = major; -function major(a, loose) { - return new SemVer(a, loose).major; -} +function translateLevel(level) { + if (level === 0) { + return false; + } -exports.minor = minor; -function minor(a, loose) { - return new SemVer(a, loose).minor; + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; } -exports.patch = patch; -function patch(a, loose) { - return new SemVer(a, loose).patch; -} +function supportsColor(stream) { + if (forceColor === false) { + return 0; + } -exports.compare = compare; -function compare(a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)); -} + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } -exports.compareLoose = compareLoose; -function compareLoose(a, b) { - return compare(a, b, true); -} + if (hasFlag('color=256')) { + return 2; + } -exports.rcompare = rcompare; -function rcompare(a, b, loose) { - return compare(b, a, loose); -} + if (stream && !stream.isTTY && forceColor !== true) { + // VS code debugger doesn't have isTTY set + if (env.VSCODE_PID) { + return 1; + } + return 0; + } -exports.sort = sort; -function sort(list, loose) { - return list.sort(function(a, b) { - return exports.compare(a, b, loose); - }); -} + const min = forceColor ? 1 : 0; -exports.rsort = rsort; -function rsort(list, loose) { - return list.sort(function(a, b) { - return exports.rcompare(a, b, loose); - }); -} + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. 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(process.versions.node.split('.')[0]) >= 8 && + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } -exports.gt = gt; -function gt(a, b, loose) { - return compare(a, b, loose) > 0; -} + return 1; + } -exports.lt = lt; -function lt(a, b, loose) { - return compare(a, b, loose) < 0; -} + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } -exports.eq = eq; -function eq(a, b, loose) { - return compare(a, b, loose) === 0; -} + return min; + } -exports.neq = neq; -function neq(a, b, loose) { - return compare(a, b, loose) !== 0; -} + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } -exports.gte = gte; -function gte(a, b, loose) { - return compare(a, b, loose) >= 0; -} + if (env.COLORTERM === 'truecolor') { + return 3; + } -exports.lte = lte; -function lte(a, b, loose) { - return compare(a, b, loose) <= 0; -} + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); -exports.cmp = cmp; -function cmp(a, op, b, loose) { - var ret; - switch (op) { - case '===': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a === b; - break; - case '!==': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a !== b; - break; - case '': case '=': case '==': ret = eq(a, b, loose); break; - case '!=': ret = neq(a, b, loose); break; - case '>': ret = gt(a, b, loose); break; - case '>=': ret = gte(a, b, loose); break; - case '<': ret = lt(a, b, loose); break; - case '<=': ret = lte(a, b, loose); break; - default: throw new TypeError('Invalid operator: ' + op); - } - return ret; -} + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } -exports.Comparator = Comparator; -function Comparator(comp, loose) { - if (comp instanceof Comparator) { - if (comp.loose === loose) - return comp; - else - comp = comp.value; - } + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } - if (!(this instanceof Comparator)) - return new Comparator(comp, loose); + if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } - debug('comparator', comp, loose); - this.loose = loose; - this.parse(comp); + if ('COLORTERM' in env) { + return 1; + } - if (this.semver === ANY) - this.value = ''; - else - this.value = this.operator + this.semver.version; + if (env.TERM === 'dumb') { + return min; + } - debug('comp', this); + return min; } -var ANY = {}; -Comparator.prototype.parse = function(comp) { - var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var m = comp.match(r); - - if (!m) - throw new TypeError('Invalid comparator: ' + comp); - - this.operator = m[1]; - if (this.operator === '=') - this.operator = ''; - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) - this.semver = ANY; - else - this.semver = new SemVer(m[2], this.loose); -}; +function getSupportLevel(stream) { + const level = supportsColor(stream); + return translateLevel(level); +} -Comparator.prototype.toString = function() { - return this.value; +module.exports = { + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr) }; -Comparator.prototype.test = function(version) { - debug('Comparator.test', version, this.loose); - - if (this.semver === ANY) - return true; - - if (typeof version === 'string') - version = new SemVer(version, this.loose); - return cmp(version, this.operator, this.semver, this.loose); -}; +/***/ }), +/* 72 */ +/***/ (function(module, exports, __webpack_require__) { -Comparator.prototype.intersects = function(comp, loose) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required'); - } +"use strict"; - var rangeTmp; +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; - if (this.operator === '') { - rangeTmp = new Range(comp.value, loose); - return satisfies(this.value, rangeTmp, loose); - } else if (comp.operator === '') { - rangeTmp = new Range(this.value, loose); - return satisfies(comp.semver, rangeTmp, loose); - } +const ESCAPES = new Map([ + ['n', '\n'], + ['r', '\r'], + ['t', '\t'], + ['b', '\b'], + ['f', '\f'], + ['v', '\v'], + ['0', '\0'], + ['\\', '\\'], + ['e', '\u001B'], + ['a', '\u0007'] +]); - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>'); - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<'); - var sameSemVer = this.semver.version === comp.semver.version; - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<='); - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, loose) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')); - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, loose) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')); +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 sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; -}; + return ESCAPES.get(c) || c; +} +function parseArguments(name, args) { + const results = []; + const chunks = args.trim().split(/\s*,\s*/g); + let matches; -exports.Range = Range; -function Range(range, loose) { - if (range instanceof Range) { - if (range.loose === loose) { - return range; - } else { - return new Range(range.raw, loose); - } - } + 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}')`); + } + } - if (range instanceof Comparator) { - return new Range(range.value, loose); - } + return results; +} - if (!(this instanceof Range)) - return new Range(range, loose); +function parseStyle(style) { + STYLE_REGEX.lastIndex = 0; - this.loose = loose; + const results = []; + let matches; - // First, split based on boolean or || - this.raw = range; - this.set = range.split(/\s*\|\|\s*/).map(function(range) { - return this.parseRange(range.trim()); - }, this).filter(function(c) { - // throw out any that are not relevant for whatever reason - return c.length; - }); + while ((matches = STYLE_REGEX.exec(style)) !== null) { + const name = matches[1]; - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range); - } + if (matches[2]) { + const args = parseArguments(name, matches[2]); + results.push([name].concat(args)); + } else { + results.push([name]); + } + } - this.format(); + return results; } -Range.prototype.format = function() { - this.range = this.set.map(function(comps) { - return comps.join(' ').trim(); - }).join('||').trim(); - return this.range; -}; +function buildStyle(chalk, styles) { + const enabled = {}; -Range.prototype.toString = function() { - return this.range; -}; + for (const layer of styles) { + for (const style of layer.styles) { + enabled[style[0]] = layer.inverse ? null : style.slice(1); + } + } -Range.prototype.parseRange = function(range) { - var loose = this.loose; - range = range.trim(); - debug('range', range, loose); - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; - range = range.replace(hr, hyphenReplace); - debug('hyphen replace', range); - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); - debug('comparator trim', range, re[COMPARATORTRIM]); + 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}`); + } - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace); + if (enabled[styleName].length > 0) { + current = current[styleName].apply(current, enabled[styleName]); + } else { + current = current[styleName]; + } + } + } - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace); + return current; +} - // normalize spaces - range = range.split(/\s+/).join(' '); +module.exports = (chalk, tmp) => { + const styles = []; + const chunks = []; + let chunk = []; - // At this point, the range is completely trimmed and - // ready to be split into comparators. + // 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'); + } - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var set = range.split(' ').map(function(comp) { - return parseComparator(comp, loose); - }).join(' ').split(/\s+/); - if (this.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function(comp) { - return !!comp.match(compRe); - }); - } - set = set.map(function(comp) { - return new Comparator(comp, loose); - }); + chunks.push(buildStyle(chalk, styles)(chunk.join(''))); + chunk = []; + styles.pop(); + } else { + chunk.push(chr); + } + }); - return set; -}; + chunks.push(chunk.join('')); -Range.prototype.intersects = function(range, loose) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required'); - } + if (styles.length > 0) { + const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; + throw new Error(errMsg); + } - return this.set.some(function(thisComparators) { - return thisComparators.every(function(thisComparator) { - return range.set.some(function(rangeComparators) { - return rangeComparators.every(function(rangeComparator) { - return thisComparator.intersects(rangeComparator, loose); - }); - }); - }); - }); + return chunks.join(''); }; -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators; -function toComparators(range, loose) { - return new Range(range, loose).set.map(function(comp) { - return comp.map(function(c) { - return c.value; - }).join(' ').trim().split(' '); - }); -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator(comp, loose) { - debug('comp', comp); - comp = replaceCarets(comp, loose); - debug('caret', comp); - comp = replaceTildes(comp, loose); - debug('tildes', comp); - comp = replaceXRanges(comp, loose); - debug('xrange', comp); - comp = replaceStars(comp, loose); - debug('stars', comp); - return comp; -} - -function isX(id) { - return !id || id.toLowerCase() === 'x' || id === '*'; -} -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceTilde(comp, loose); - }).join(' '); -} +/***/ }), +/* 73 */ +/***/ (function(module, exports, __webpack_require__) { -function replaceTilde(comp, loose) { - var r = loose ? re[TILDELOOSE] : re[TILDE]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr); - var ret; +module.exports = normalize - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else if (pr) { - debug('replaceTilde pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; +var fixer = __webpack_require__(74) +normalize.fixer = fixer - debug('tilde return', ret); - return ret; - }); -} +var makeWarning = __webpack_require__(96) -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceCaret(comp, loose); - }).join(' '); -} +var fieldsToFix = ['name','version','description','repository','modules','scripts' + ,'files','bin','man','bugs','keywords','readme','homepage','license'] +var otherThingsToFix = ['dependencies','people', 'typos'] -function replaceCaret(comp, loose) { - debug('caret', comp, loose); - var r = loose ? re[CARETLOOSE] : re[CARET]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr); - var ret; +var thingsToFix = fieldsToFix.map(function(fieldName) { + return ucFirst(fieldName) + "Field" +}) +// two ways to do this in CoffeeScript on only one line, sub-70 chars: +// thingsToFix = fieldsToFix.map (name) -> ucFirst(name) + "Field" +// thingsToFix = (ucFirst(name) + "Field" for name in fieldsToFix) +thingsToFix = thingsToFix.concat(otherThingsToFix) - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) { - if (M === '0') - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; - } else if (pr) { - debug('replaceCaret pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + (+M + 1) + '.0.0'; - } else { - debug('no pr'); - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0'; - } +function normalize (data, warn, strict) { + if(warn === true) warn = null, strict = true + if(!strict) strict = false + if(!warn || data.private) warn = function(msg) { /* noop */ } - debug('caret return', ret); - return ret; - }); + if (data.scripts && + data.scripts.install === "node-gyp rebuild" && + !data.scripts.preinstall) { + data.gypfile = true + } + fixer.warn = function() { warn(makeWarning.apply(null, arguments)) } + thingsToFix.forEach(function(thingName) { + fixer["fix" + ucFirst(thingName)](data, strict) + }) + data._id = data.name + "@" + data.version } -function replaceXRanges(comp, loose) { - debug('replaceXRanges', comp, loose); - return comp.split(/\s+/).map(function(comp) { - return replaceXRange(comp, loose); - }).join(' '); +function ucFirst (string) { + return string.charAt(0).toUpperCase() + string.slice(1); } -function replaceXRange(comp, loose) { - comp = comp.trim(); - var r = loose ? re[XRANGELOOSE] : re[XRANGE]; - return comp.replace(r, function(ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr); - var xM = isX(M); - var xm = xM || isX(m); - var xp = xm || isX(p); - var anyX = xp; - if (gtlt === '=' && anyX) - gtlt = ''; +/***/ }), +/* 74 */ +/***/ (function(module, exports, __webpack_require__) { - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0'; - } else { - // nothing is forbidden - ret = '*'; - } - } else if (gtlt && anyX) { - // replace X with 0 - if (xm) - m = 0; - if (xp) - p = 0; +var semver = __webpack_require__(75) +var validateLicense = __webpack_require__(76); +var hostedGitInfo = __webpack_require__(81) +var isBuiltinModule = __webpack_require__(85).isCore +var depTypes = ["dependencies","devDependencies","optionalDependencies"] +var extractDescription = __webpack_require__(94) +var url = __webpack_require__(82) +var typos = __webpack_require__(95) - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>='; - if (xm) { - M = +M + 1; - m = 0; - p = 0; - } else if (xp) { - m = +m + 1; - p = 0; - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<'; - if (xm) - M = +M + 1; - else - m = +m + 1; - } +var fixer = module.exports = { + // default warning function + warn: function() {}, - ret = gtlt + M + '.' + m + '.' + p; - } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + fixRepositoryField: function(data) { + if (data.repositories) { + this.warn("repositories"); + data.repository = data.repositories[0] + } + if (!data.repository) return this.warn("missingRepository") + if (typeof data.repository === "string") { + data.repository = { + type: "git", + url: data.repository + } + } + var r = data.repository.url || "" + if (r) { + var hosted = hostedGitInfo.fromUrl(r) + if (hosted) { + r = data.repository.url + = hosted.getDefaultRepresentation() == "shortcut" ? hosted.https() : hosted.toString() + } } - debug('xRange return', ret); - - return ret; - }); -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars(comp, loose) { - debug('replaceStars', comp, loose); - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], ''); -} - -// This function is passed to string.replace(re[HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - - if (isX(fM)) - from = ''; - else if (isX(fm)) - from = '>=' + fM + '.0.0'; - else if (isX(fp)) - from = '>=' + fM + '.' + fm + '.0'; - else - from = '>=' + from; - - if (isX(tM)) - to = ''; - else if (isX(tm)) - to = '<' + (+tM + 1) + '.0.0'; - else if (isX(tp)) - to = '<' + tM + '.' + (+tm + 1) + '.0'; - else if (tpr) - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; - else - to = '<=' + to; - - return (from + ' ' + to).trim(); -} - - -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function(version) { - if (!version) - return false; - - if (typeof version === 'string') - version = new SemVer(version, this.loose); - - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version)) - return true; + if (r.match(/github.com\/[^\/]+\/[^\/]+\.git\.git$/)) { + this.warn("brokenGitUrl", r) + } } - return false; -}; -function testSet(set, version) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) - return false; +, fixTypos: function(data) { + Object.keys(typos.topLevel).forEach(function (d) { + if (data.hasOwnProperty(d)) { + this.warn("typo", d, typos.topLevel[d]) + } + }, this) } - if (version.prerelease.length) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (var i = 0; i < set.length; i++) { - debug(set[i].semver); - if (set[i].semver === ANY) - continue; - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver; - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) - return true; - } +, fixScriptsField: function(data) { + if (!data.scripts) return + if (typeof data.scripts !== "object") { + this.warn("nonObjectScripts") + delete data.scripts + return } - - // Version has a -pre, but it's not one of the ones we like. - return false; + Object.keys(data.scripts).forEach(function (k) { + if (typeof data.scripts[k] !== "string") { + this.warn("nonStringScript") + delete data.scripts[k] + } else if (typos.script[k] && !data.scripts[typos.script[k]]) { + this.warn("typo", k, typos.script[k], "scripts") + } + }, this) } - return true; -} - -exports.satisfies = satisfies; -function satisfies(version, range, loose) { - try { - range = new Range(range, loose); - } catch (er) { - return false; +, fixFilesField: function(data) { + var files = data.files + if (files && !Array.isArray(files)) { + this.warn("nonArrayFiles") + delete data.files + } else if (data.files) { + data.files = data.files.filter(function(file) { + if (!file || typeof file !== "string") { + this.warn("invalidFilename", file) + return false + } else { + return true + } + }, this) + } } - return range.test(version); -} -exports.maxSatisfying = maxSatisfying; -function maxSatisfying(versions, range, loose) { - var max = null; - var maxSV = null; - try { - var rangeObj = new Range(range, loose); - } catch (er) { - return null; - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!max || maxSV.compare(v) === -1) { // compare(max, v, true) - max = v; - maxSV = new SemVer(max, loose); +, fixBinField: function(data) { + if (!data.bin) return; + if (typeof data.bin === "string") { + var b = {} + var match + if (match = data.name.match(/^@[^/]+[/](.*)$/)) { + b[match[1]] = data.bin + } else { + b[data.name] = data.bin } + data.bin = b } - }) - return max; -} + } -exports.minSatisfying = minSatisfying; -function minSatisfying(versions, range, loose) { - var min = null; - var minSV = null; - try { - var rangeObj = new Range(range, loose); - } catch (er) { - return null; +, fixManField: function(data) { + if (!data.man) return; + if (typeof data.man === "string") { + data.man = [ data.man ] + } } - versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!min || minSV.compare(v) === 1) { // compare(min, v, true) - min = v; - minSV = new SemVer(min, loose); - } +, fixBundleDependenciesField: function(data) { + var bdd = "bundledDependencies" + var bd = "bundleDependencies" + if (data[bdd] && !data[bd]) { + data[bd] = data[bdd] + delete data[bdd] } - }) - return min; -} + if (data[bd] && !Array.isArray(data[bd])) { + this.warn("nonArrayBundleDependencies") + delete data[bd] + } else if (data[bd]) { + data[bd] = data[bd].filter(function(bd) { + if (!bd || typeof bd !== 'string') { + this.warn("nonStringBundleDependency", bd) + return false + } else { + if (!data.dependencies) { + data.dependencies = {} + } + if (!data.dependencies.hasOwnProperty(bd)) { + this.warn("nonDependencyBundleDependency", bd) + data.dependencies[bd] = "*" + } + return true + } + }, this) + } + } -exports.validRange = validRange; -function validRange(range, loose) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, loose).range || '*'; - } catch (er) { - return null; +, fixDependencies: function(data, strict) { + var loose = !strict + objectifyDeps(data, this.warn) + addOptionalDepsToDeps(data, this.warn) + this.fixBundleDependenciesField(data) + + ;['dependencies','devDependencies'].forEach(function(deps) { + if (!(deps in data)) return + if (!data[deps] || typeof data[deps] !== "object") { + this.warn("nonObjectDependencies", deps) + delete data[deps] + return + } + Object.keys(data[deps]).forEach(function (d) { + var r = data[deps][d] + if (typeof r !== 'string') { + this.warn("nonStringDependency", d, JSON.stringify(r)) + delete data[deps][d] + } + var hosted = hostedGitInfo.fromUrl(data[deps][d]) + if (hosted) data[deps][d] = hosted.toString() + }, this) + }, this) } -} -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr; -function ltr(version, range, loose) { - return outside(version, range, '<', loose); -} +, fixModulesField: function (data) { + if (data.modules) { + this.warn("deprecatedModules") + delete data.modules + } + } -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr; -function gtr(version, range, loose) { - return outside(version, range, '>', loose); -} +, fixKeywordsField: function (data) { + if (typeof data.keywords === "string") { + data.keywords = data.keywords.split(/,\s+/) + } + if (data.keywords && !Array.isArray(data.keywords)) { + delete data.keywords + this.warn("nonArrayKeywords") + } else if (data.keywords) { + data.keywords = data.keywords.filter(function(kw) { + if (typeof kw !== "string" || !kw) { + this.warn("nonStringKeyword"); + return false + } else { + return true + } + }, this) + } + } -exports.outside = outside; -function outside(version, range, hilo, loose) { - version = new SemVer(version, loose); - range = new Range(range, loose); +, fixVersionField: function(data, strict) { + // allow "loose" semver 1.0 versions in non-strict mode + // enforce strict semver 2.0 compliance in strict mode + var loose = !strict + if (!data.version) { + data.version = "" + return true + } + if (!semver.valid(data.version, loose)) { + throw new Error('Invalid version: "'+ data.version + '"') + } + data.version = semver.clean(data.version, loose) + return true + } - var gtfn, ltefn, ltfn, comp, ecomp; - switch (hilo) { - case '>': - gtfn = gt; - ltefn = lte; - ltfn = lt; - comp = '>'; - ecomp = '>='; - break; - case '<': - gtfn = lt; - ltefn = gte; - ltfn = gt; - comp = '<'; - ecomp = '<='; - break; - default: - throw new TypeError('Must provide a hilo val of "<" or ">"'); +, fixPeople: function(data) { + modifyPeople(data, unParsePerson) + modifyPeople(data, parsePerson) } - // If it satisifes the range it is not outside - if (satisfies(version, range, loose)) { - return false; +, fixNameField: function(data, options) { + if (typeof options === "boolean") options = {strict: options} + else if (typeof options === "undefined") options = {} + var strict = options.strict + if (!data.name && !strict) { + data.name = "" + return + } + if (typeof data.name !== "string") { + throw new Error("name field must be a string.") + } + if (!strict) + data.name = data.name.trim() + ensureValidName(data.name, strict, options.allowLegacyCase) + if (isBuiltinModule(data.name)) + this.warn("conflictingName", data.name) } - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i]; +, fixDescriptionField: function (data) { + if (data.description && typeof data.description !== 'string') { + this.warn("nonStringDescription") + delete data.description + } + if (data.readme && !data.description) + data.description = extractDescription(data.readme) + if(data.description === undefined) delete data.description; + if (!data.description) this.warn("missingDescription") + } - var high = null; - var low = null; +, fixReadmeField: function (data) { + if (!data.readme) { + this.warn("missingReadme") + data.readme = "ERROR: No README data found!" + } + } - comparators.forEach(function(comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') +, fixBugsField: function(data) { + if (!data.bugs && data.repository && data.repository.url) { + var hosted = hostedGitInfo.fromUrl(data.repository.url) + if(hosted && hosted.bugs()) { + data.bugs = {url: hosted.bugs()} } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, loose)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, loose)) { - low = comparator; + } + else if(data.bugs) { + var emailRe = /^.+@.*\..+$/ + if(typeof data.bugs == "string") { + if(emailRe.test(data.bugs)) + data.bugs = {email:data.bugs} + else if(url.parse(data.bugs).protocol) + data.bugs = {url: data.bugs} + else + this.warn("nonEmailUrlBugsString") } - }); + else { + bugsTypos(data.bugs, this.warn) + var oldBugs = data.bugs + data.bugs = {} + if(oldBugs.url) { + if(typeof(oldBugs.url) == "string" && url.parse(oldBugs.url).protocol) + data.bugs.url = oldBugs.url + else + this.warn("nonUrlBugsUrlField") + } + if(oldBugs.email) { + if(typeof(oldBugs.email) == "string" && emailRe.test(oldBugs.email)) + data.bugs.email = oldBugs.email + else + this.warn("nonEmailBugsEmailField") + } + } + if(!data.bugs.email && !data.bugs.url) { + delete data.bugs + this.warn("emptyNormalizedBugs") + } + } + } - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false; +, fixHomepageField: function(data) { + if (!data.homepage && data.repository && data.repository.url) { + var hosted = hostedGitInfo.fromUrl(data.repository.url) + if (hosted && hosted.docs()) data.homepage = hosted.docs() } + if (!data.homepage) return - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false; - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false; + if(typeof data.homepage !== "string") { + this.warn("nonUrlHomepage") + return delete data.homepage + } + if(!url.parse(data.homepage).protocol) { + data.homepage = "http://" + data.homepage } } - return true; -} -exports.prerelease = prerelease; -function prerelease(version, loose) { - var parsed = parse(version, loose); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; +, fixLicenseField: function(data) { + if (!data.license) { + return this.warn("missingLicense") + } else{ + if ( + typeof(data.license) !== 'string' || + data.license.length < 1 || + data.license.trim() === '' + ) { + this.warn("invalidLicense") + } else { + if (!validateLicense(data.license).validForNewPackages) + this.warn("invalidLicense") + } + } + } } -exports.intersects = intersects; -function intersects(r1, r2, loose) { - r1 = new Range(r1, loose) - r2 = new Range(r2, loose) - return r1.intersects(r2) +function isValidScopedPackageName(spec) { + if (spec.charAt(0) !== '@') return false + + var rest = spec.slice(1).split('/') + if (rest.length !== 2) return false + + return rest[0] && rest[1] && + rest[0] === encodeURIComponent(rest[0]) && + rest[1] === encodeURIComponent(rest[1]) } +function isCorrectlyEncodedName(spec) { + return !spec.match(/[\/@\s\+%:]/) && + spec === encodeURIComponent(spec) +} -/***/ }), -/* 68 */ -/***/ (function(module, exports, __webpack_require__) { +function ensureValidName (name, strict, allowLegacyCase) { + if (name.charAt(0) === "." || + !(isValidScopedPackageName(name) || isCorrectlyEncodedName(name)) || + (strict && (!allowLegacyCase) && name !== name.toLowerCase()) || + name.toLowerCase() === "node_modules" || + name.toLowerCase() === "favicon.ico") { + throw new Error("Invalid name: " + JSON.stringify(name)) + } +} -var parse = __webpack_require__(69); -var correct = __webpack_require__(71); +function modifyPeople (data, fn) { + if (data.author) data.author = fn(data.author) + ;["maintainers", "contributors"].forEach(function (set) { + if (!Array.isArray(data[set])) return; + data[set] = data[set].map(fn) + }) + return data +} -var genericWarning = ( - 'license should be ' + - 'a valid SPDX license expression (without "LicenseRef"), ' + - '"UNLICENSED", or ' + - '"SEE LICENSE IN "' -); +function unParsePerson (person) { + if (typeof person === "string") return person + var name = person.name || "" + var u = person.url || person.web + var url = u ? (" ("+u+")") : "" + var e = person.email || person.mail + var email = e ? (" <"+e+">") : "" + return name+email+url +} -var fileReferenceRE = /^SEE LICEN[CS]E IN (.+)$/; +function parsePerson (person) { + if (typeof person !== "string") return person + var name = person.match(/^([^\(<]+)/) + var url = person.match(/\(([^\)]+)\)/) + var email = person.match(/<([^>]+)>/) + var obj = {} + if (name && name[0].trim()) obj.name = name[0].trim() + if (email) obj.email = email[1]; + if (url) obj.url = url[1]; + return obj +} -function startsWith(prefix, string) { - return string.slice(0, prefix.length) === prefix; +function addOptionalDepsToDeps (data, warn) { + var o = data.optionalDependencies + if (!o) return; + var d = data.dependencies || {} + Object.keys(o).forEach(function (k) { + d[k] = o[k] + }) + data.dependencies = d } -function usesLicenseRef(ast) { - if (ast.hasOwnProperty('license')) { - var license = ast.license; - return ( - startsWith('LicenseRef', license) || - startsWith('DocumentRef', license) - ); - } else { - return ( - usesLicenseRef(ast.left) || - usesLicenseRef(ast.right) - ); +function depObjectify (deps, type, warn) { + if (!deps) return {} + if (typeof deps === "string") { + deps = deps.trim().split(/[\n\r\s\t ,]+/) } + if (!Array.isArray(deps)) return deps + warn("deprecatedArrayDependencies", type) + var o = {} + deps.filter(function (d) { + return typeof d === "string" + }).forEach(function(d) { + d = d.trim().split(/(:?[@\s><=])/) + var dn = d.shift() + var dv = d.join("") + dv = dv.trim() + dv = dv.replace(/^@/, "") + o[dn] = dv + }) + return o } -module.exports = function(argument) { - var ast; +function objectifyDeps (data, warn) { + depTypes.forEach(function (type) { + if (!data[type]) return; + data[type] = depObjectify(data[type], type, warn) + }) +} - try { - ast = parse(argument); - } catch (e) { - var match - if ( - argument === 'UNLICENSED' || - argument === 'UNLICENCED' - ) { - return { - validForOldPackages: true, - validForNewPackages: true, - unlicensed: true - }; - } else if (match = fileReferenceRE.exec(argument)) { - return { - validForOldPackages: true, - validForNewPackages: true, - inFile: match[1] - }; - } else { - var result = { - validForOldPackages: false, - validForNewPackages: false, - warnings: [genericWarning] - }; - var corrected = correct(argument); - if (corrected) { - result.warnings.push( - 'license is similar to the valid expression "' + corrected + '"' - ); - } - return result; +function bugsTypos(bugs, warn) { + if (!bugs) return + Object.keys(bugs).forEach(function (k) { + if (typos.bugs[k]) { + warn("typo", k, typos.bugs[k], "bugs") + bugs[typos.bugs[k]] = bugs[k] + delete bugs[k] } - } - - if (usesLicenseRef(ast)) { - return { - validForNewPackages: false, - validForOldPackages: false, - spdx: true, - warnings: [genericWarning] - }; - } else { - return { - validForNewPackages: true, - validForOldPackages: true, - spdx: true - }; - } -}; + }) +} /***/ }), -/* 69 */ -/***/ (function(module, exports, __webpack_require__) { +/* 75 */ +/***/ (function(module, exports) { -var parser = __webpack_require__(70).parser +exports = module.exports = SemVer; -module.exports = function (argument) { - return parser.parse(argument) -} +// The debug function is excluded entirely from the minified version. +/* nomin */ var debug; +/* nomin */ if (typeof process === 'object' && + /* nomin */ process.env && + /* nomin */ process.env.NODE_DEBUG && + /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) + /* nomin */ debug = function() { + /* nomin */ var args = Array.prototype.slice.call(arguments, 0); + /* nomin */ args.unshift('SEMVER'); + /* nomin */ console.log.apply(console, args); + /* nomin */ }; +/* nomin */ else + /* nomin */ debug = function() {}; +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0'; -/***/ }), -/* 70 */ -/***/ (function(module, exports, __webpack_require__) { +var MAX_LENGTH = 256; +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; -/* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */ -/* - Returns a Parser object of the following structure: +// The actual regexps go on exports.re +var re = exports.re = []; +var src = exports.src = []; +var R = 0; - Parser: { - yy: {} - } +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. - Parser.prototype: { - yy: {}, - trace: function(), - symbols_: {associative list: name ==> number}, - terminals_: {associative list: number ==> name}, - productions_: [...], - performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), - table: [...], - defaultActions: {...}, - parseError: function(str, hash), - parse: function(input), +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. - lexer: { - EOF: 1, - parseError: function(str, hash), - setInput: function(input), - input: function(), - unput: function(str), - more: function(), - less: function(n), - pastInput: function(), - upcomingInput: function(), - showPosition: function(), - test_match: function(regex_match_array, rule_index), - next: function(), - lex: function(), - begin: function(condition), - popState: function(), - _currentRules: function(), - topState: function(), - pushState: function(condition), +var NUMERICIDENTIFIER = R++; +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; +var NUMERICIDENTIFIERLOOSE = R++; +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; - options: { - ranges: boolean (optional: true ==> token location info will include a .range[] member) - flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) - backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) - }, - performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), - rules: [...], - conditions: {associative list: name ==> set}, - } - } +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. +var NONNUMERICIDENTIFIER = R++; +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; - token location info (@$, _$, etc.): { - first_line: n, - last_line: n, - first_column: n, - last_column: n, - range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) - } +// ## Main Version +// Three dot-separated numeric identifiers. - the parseError function receives a 'hash' object with these members for lexer and parser errors: { - text: (matched text) - token: (the produced terminal token, if any) - line: (yylineno) - } - while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { - loc: (yylloc) - expected: (string describing the set of expected tokens) - recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) - } -*/ -var spdxparse = (function(){ -var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,6],$V2=[1,7],$V3=[1,4],$V4=[1,9],$V5=[1,10],$V6=[5,14,15,17],$V7=[5,12,14,15,17]; -var parser = {trace: function trace() { }, -yy: {}, -symbols_: {"error":2,"start":3,"expression":4,"EOS":5,"simpleExpression":6,"LICENSE":7,"PLUS":8,"LICENSEREF":9,"DOCUMENTREF":10,"COLON":11,"WITH":12,"EXCEPTION":13,"AND":14,"OR":15,"OPEN":16,"CLOSE":17,"$accept":0,"$end":1}, -terminals_: {2:"error",5:"EOS",7:"LICENSE",8:"PLUS",9:"LICENSEREF",10:"DOCUMENTREF",11:"COLON",12:"WITH",13:"EXCEPTION",14:"AND",15:"OR",16:"OPEN",17:"CLOSE"}, -productions_: [0,[3,2],[6,1],[6,2],[6,1],[6,3],[4,1],[4,3],[4,3],[4,3],[4,3]], -performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { -/* this == yyval */ +var MAINVERSION = R++; +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')'; -var $0 = $$.length - 1; -switch (yystate) { -case 1: -return this.$ = $$[$0-1] -break; -case 2: case 4: case 5: -this.$ = {license: yytext} -break; -case 3: -this.$ = {license: $$[$0-1], plus: true} -break; -case 6: -this.$ = $$[$0] -break; -case 7: -this.$ = {exception: $$[$0]} -this.$.license = $$[$0-2].license -if ($$[$0-2].hasOwnProperty('plus')) { - this.$.plus = $$[$0-2].plus -} -break; -case 8: -this.$ = {conjunction: 'and', left: $$[$0-2], right: $$[$0]} -break; -case 9: -this.$ = {conjunction: 'or', left: $$[$0-2], right: $$[$0]} -break; -case 10: -this.$ = $$[$0-1] -break; -} -}, -table: [{3:1,4:2,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{1:[3]},{5:[1,8],14:$V4,15:$V5},o($V6,[2,6],{12:[1,11]}),{4:12,6:3,7:$V0,9:$V1,10:$V2,16:$V3},o($V7,[2,2],{8:[1,13]}),o($V7,[2,4]),{11:[1,14]},{1:[2,1]},{4:15,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{4:16,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{13:[1,17]},{14:$V4,15:$V5,17:[1,18]},o($V7,[2,3]),{9:[1,19]},o($V6,[2,8]),o([5,15,17],[2,9],{14:$V4}),o($V6,[2,7]),o($V6,[2,10]),o($V7,[2,5])], -defaultActions: {8:[2,1]}, -parseError: function parseError(str, hash) { - if (hash.recoverable) { - this.trace(str); - } else { - function _parseError (msg, hash) { - this.message = msg; - this.hash = hash; - } - _parseError.prototype = Error; +var MAINVERSIONLOOSE = R++; +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; - throw new _parseError(str, hash); - } -}, -parse: function parse(input) { - var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; - var args = lstack.slice.call(arguments, 1); - var lexer = Object.create(this.lexer); - var sharedState = { yy: {} }; - for (var k in this.yy) { - if (Object.prototype.hasOwnProperty.call(this.yy, k)) { - sharedState.yy[k] = this.yy[k]; - } - } - lexer.setInput(input, sharedState.yy); - sharedState.yy.lexer = lexer; - sharedState.yy.parser = this; - if (typeof lexer.yylloc == 'undefined') { - lexer.yylloc = {}; - } - var yyloc = lexer.yylloc; - lstack.push(yyloc); - var ranges = lexer.options && lexer.options.ranges; - if (typeof sharedState.yy.parseError === 'function') { - this.parseError = sharedState.yy.parseError; - } else { - this.parseError = Object.getPrototypeOf(this).parseError; - } - function popStack(n) { - stack.length = stack.length - 2 * n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - _token_stack: - var lex = function () { - var token; - token = lexer.lex() || EOF; - if (typeof token !== 'number') { - token = self.symbols_[token] || token; - } - return token; - }; - var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; - while (true) { - state = stack[stack.length - 1]; - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol === null || typeof symbol == 'undefined') { - symbol = lex(); - } - action = table[state] && table[state][symbol]; - } - if (typeof action === 'undefined' || !action.length || !action[0]) { - var errStr = ''; - expected = []; - for (p in table[state]) { - if (this.terminals_[p] && p > TERROR) { - expected.push('\'' + this.terminals_[p] + '\''); - } - } - if (lexer.showPosition) { - errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; - } else { - errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); - } - this.parseError(errStr, { - text: lexer.match, - token: this.terminals_[symbol] || symbol, - line: lexer.yylineno, - loc: yyloc, - expected: expected - }); - } - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); - } - switch (action[0]) { - case 1: - stack.push(symbol); - vstack.push(lexer.yytext); - lstack.push(lexer.yylloc); - stack.push(action[1]); - symbol = null; - if (!preErrorSymbol) { - yyleng = lexer.yyleng; - yytext = lexer.yytext; - yylineno = lexer.yylineno; - yyloc = lexer.yylloc; - if (recovering > 0) { - recovering--; - } - } else { - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - case 2: - len = this.productions_[action[1]][1]; - yyval.$ = vstack[vstack.length - len]; - yyval._$ = { - first_line: lstack[lstack.length - (len || 1)].first_line, - last_line: lstack[lstack.length - 1].last_line, - first_column: lstack[lstack.length - (len || 1)].first_column, - last_column: lstack[lstack.length - 1].last_column - }; - if (ranges) { - yyval._$.range = [ - lstack[lstack.length - (len || 1)].range[0], - lstack[lstack.length - 1].range[1] - ]; - } - r = this.performAction.apply(yyval, [ - yytext, - yyleng, - yylineno, - sharedState.yy, - action[1], - vstack, - lstack - ].concat(args)); - if (typeof r !== 'undefined') { - return r; - } - if (len) { - stack = stack.slice(0, -1 * len * 2); - vstack = vstack.slice(0, -1 * len); - lstack = lstack.slice(0, -1 * len); - } - stack.push(this.productions_[action[1]][0]); - vstack.push(yyval.$); - lstack.push(yyval._$); - newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; - stack.push(newState); - break; - case 3: - return true; - } - } - return true; -}}; -/* generated by jison-lex 0.3.4 */ -var lexer = (function(){ -var lexer = ({ +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. -EOF:1, +var PRERELEASEIDENTIFIER = R++; +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; -parseError:function parseError(str, hash) { - if (this.yy.parser) { - this.yy.parser.parseError(str, hash); - } else { - throw new Error(str); - } - }, +var PRERELEASEIDENTIFIERLOOSE = R++; +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; -// resets the lexer, sets new input -setInput:function (input, yy) { - this.yy = yy || this.yy || {}; - this._input = input; - this._more = this._backtrack = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = { - first_line: 1, - first_column: 0, - last_line: 1, - last_column: 0 - }; - if (this.options.ranges) { - this.yylloc.range = [0,0]; - } - this.offset = 0; - return this; - }, -// consumes and returns one char from the input -input:function () { - var ch = this._input[0]; - this.yytext += ch; - this.yyleng++; - this.offset++; - this.match += ch; - this.matched += ch; - var lines = ch.match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno++; - this.yylloc.last_line++; - } else { - this.yylloc.last_column++; - } - if (this.options.ranges) { - this.yylloc.range[1]++; - } +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. - this._input = this._input.slice(1); - return ch; - }, +var PRERELEASE = R++; +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; -// unshifts one char (or a string) into the input -unput:function (ch) { - var len = ch.length; - var lines = ch.split(/(?:\r\n?|\n)/g); +var PRERELEASELOOSE = R++; +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; - this._input = ch + this._input; - this.yytext = this.yytext.substr(0, this.yytext.length - len); - //this.yyleng -= len; - this.offset -= len; - var oldLines = this.match.split(/(?:\r\n?|\n)/g); - this.match = this.match.substr(0, this.match.length - 1); - this.matched = this.matched.substr(0, this.matched.length - 1); +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. - if (lines.length - 1) { - this.yylineno -= lines.length - 1; - } - var r = this.yylloc.range; +var BUILDIDENTIFIER = R++; +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; - this.yylloc = { - first_line: this.yylloc.first_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.first_column, - last_column: lines ? - (lines.length === oldLines.length ? this.yylloc.first_column : 0) - + oldLines[oldLines.length - lines.length].length - lines[0].length : - this.yylloc.first_column - len - }; +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. - if (this.options.ranges) { - this.yylloc.range = [r[0], r[0] + this.yyleng - len]; - } - this.yyleng = this.yytext.length; - return this; - }, +var BUILD = R++; +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; -// When called from action, caches matched text and appends it on next action -more:function () { - this._more = true; - return this; - }, -// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. -reject:function () { - if (this.options.backtrack_lexer) { - this._backtrack = true; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. - } - return this; - }, +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. -// retain first n characters of the match -less:function (n) { - this.unput(this.match.slice(n)); - }, +var FULL = R++; +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?'; -// displays already matched input, i.e. for error messages -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, +src[FULL] = '^' + FULLPLAIN + '$'; -// displays upcoming input, i.e. for error messages -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); - }, +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?'; -// displays the character position where the lexing error occurred, i.e. for error messages -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c + "^"; - }, +var LOOSE = R++; +src[LOOSE] = '^' + LOOSEPLAIN + '$'; -// test the lexed token: return FALSE when not a match, otherwise return token -test_match:function (match, indexed_rule) { - var token, - lines, - backup; +var GTLT = R++; +src[GTLT] = '((?:<|>)?=?)'; - if (this.options.backtrack_lexer) { - // save context - backup = { - yylineno: this.yylineno, - yylloc: { - first_line: this.yylloc.first_line, - last_line: this.last_line, - first_column: this.yylloc.first_column, - last_column: this.yylloc.last_column - }, - yytext: this.yytext, - match: this.match, - matches: this.matches, - matched: this.matched, - yyleng: this.yyleng, - offset: this.offset, - _more: this._more, - _input: this._input, - yy: this.yy, - conditionStack: this.conditionStack.slice(0), - done: this.done - }; - if (this.options.ranges) { - backup.yylloc.range = this.yylloc.range.slice(0); - } - } +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++; +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; +var XRANGEIDENTIFIER = R++; +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; - lines = match[0].match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno += lines.length; - } - this.yylloc = { - first_line: this.yylloc.last_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.last_column, - last_column: lines ? - lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : - this.yylloc.last_column + match[0].length - }; - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - if (this.options.ranges) { - this.yylloc.range = [this.offset, this.offset += this.yyleng]; - } - this._more = false; - this._backtrack = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); - if (this.done && this._input) { - this.done = false; - } - if (token) { - return token; - } else if (this._backtrack) { - // recover context - for (var k in backup) { - this[k] = backup[k]; - } - return false; // rule action called reject() implying the next rule should be tested instead. - } - return false; - }, +var XRANGEPLAIN = R++; +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?'; -// return next match in input -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) { - this.done = true; - } +var XRANGEPLAINLOOSE = R++; +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?'; - var token, - match, - tempMatch, - index; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i = 0; i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (this.options.backtrack_lexer) { - token = this.test_match(tempMatch, rules[i]); - if (token !== false) { - return token; - } else if (this._backtrack) { - match = false; - continue; // rule action called reject() implying a rule MISmatch. - } else { - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; - } - } else if (!this.options.flex) { - break; - } - } +var XRANGE = R++; +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; +var XRANGELOOSE = R++; +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++; +src[LONETILDE] = '(?:~>?)'; + +var TILDETRIM = R++; +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); +var tildeTrimReplace = '$1~'; + +var TILDE = R++; +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; +var TILDELOOSE = R++; +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++; +src[LONECARET] = '(?:\\^)'; + +var CARETTRIM = R++; +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); +var caretTrimReplace = '$1^'; + +var CARET = R++; +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; +var CARETLOOSE = R++; +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++; +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; +var COMPARATOR = R++; +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++; +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); +var comparatorTrimReplace = '$1$2$3'; + + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++; +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$'; + +var HYPHENRANGELOOSE = R++; +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$'; + +// Star ranges basically just allow anything at all. +var STAR = R++; +src[STAR] = '(<|>)?=?\\s*\\*'; + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]); + if (!re[i]) + re[i] = new RegExp(src[i]); +} + +exports.parse = parse; +function parse(version, loose) { + if (version instanceof SemVer) + return version; + + if (typeof version !== 'string') + return null; + + if (version.length > MAX_LENGTH) + return null; + + var r = loose ? re[LOOSE] : re[FULL]; + if (!r.test(version)) + return null; + + try { + return new SemVer(version, loose); + } catch (er) { + return null; + } +} + +exports.valid = valid; +function valid(version, loose) { + var v = parse(version, loose); + return v ? v.version : null; +} + + +exports.clean = clean; +function clean(version, loose) { + var s = parse(version.trim().replace(/^[=v]+/, ''), loose); + return s ? s.version : null; +} + +exports.SemVer = SemVer; + +function SemVer(version, loose) { + if (version instanceof SemVer) { + if (version.loose === loose) + return version; + else + version = version.version; + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version); + } + + if (version.length > MAX_LENGTH) + throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + + if (!(this instanceof SemVer)) + return new SemVer(version, loose); + + debug('SemVer', version, loose); + this.loose = loose; + var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + + if (!m) + throw new TypeError('Invalid Version: ' + version); + + this.raw = version; + + // these are actually numbers + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) + throw new TypeError('Invalid major version') + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) + throw new TypeError('Invalid minor version') + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) + throw new TypeError('Invalid patch version') + + // numberify any prerelease numeric ids + if (!m[4]) + this.prerelease = []; + else + this.prerelease = m[4].split('.').map(function(id) { + if (/^[0-9]+$/.test(id)) { + var num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) + return num; + } + return id; + }); + + this.build = m[5] ? m[5].split('.') : []; + this.format(); +} + +SemVer.prototype.format = function() { + this.version = this.major + '.' + this.minor + '.' + this.patch; + if (this.prerelease.length) + this.version += '-' + this.prerelease.join('.'); + return this.version; +}; + +SemVer.prototype.toString = function() { + return this.version; +}; + +SemVer.prototype.compare = function(other) { + debug('SemVer.compare', this.version, this.loose, other); + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return this.compareMain(other) || this.comparePre(other); +}; + +SemVer.prototype.compareMain = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch); +}; + +SemVer.prototype.comparePre = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) + return -1; + else if (!this.prerelease.length && other.prerelease.length) + return 1; + else if (!this.prerelease.length && !other.prerelease.length) + return 0; + + var i = 0; + do { + var a = this.prerelease[i]; + var b = other.prerelease[i]; + debug('prerelease compare', i, a, b); + if (a === undefined && b === undefined) + return 0; + else if (b === undefined) + return 1; + else if (a === undefined) + return -1; + else if (a === b) + continue; + else + return compareIdentifiers(a, b); + } while (++i); +}; + +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function(release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc('pre', identifier); + break; + case 'preminor': + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc('pre', identifier); + break; + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0; + this.inc('patch', identifier); + this.inc('pre', identifier); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) + this.inc('patch', identifier); + this.inc('pre', identifier); + break; + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) + this.major++; + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) + this.minor++; + this.patch = 0; + this.prerelease = []; + break; + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) + this.patch++; + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) + this.prerelease = [0]; + else { + var i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++; + i = -2; + } } - if (match) { - token = this.test_match(match, rules[index]); - if (token !== false) { - return token; - } - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; + if (i === -1) // didn't increment anything + this.prerelease.push(0); + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) + this.prerelease = [identifier, 0]; + } else + this.prerelease = [identifier, 0]; + } + break; + + default: + throw new Error('invalid increment argument: ' + release); + } + this.format(); + this.raw = this.version; + return this; +}; + +exports.inc = inc; +function inc(version, release, loose, identifier) { + if (typeof(loose) === 'string') { + identifier = loose; + loose = undefined; + } + + try { + return new SemVer(version, loose).inc(release, identifier).version; + } catch (er) { + return null; + } +} + +exports.diff = diff; +function diff(version1, version2) { + if (eq(version1, version2)) { + return null; + } else { + var v1 = parse(version1); + var v2 = parse(version2); + if (v1.prerelease.length || v2.prerelease.length) { + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return 'pre'+key; + } } - if (this._input === "") { - return this.EOF; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); + } + return 'prerelease'; + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return key; } - }, + } + } + } +} -// return next match that has a token -lex:function lex() { - var r = this.next(); - if (r) { - return r; - } else { - return this.lex(); - } - }, +exports.compareIdentifiers = compareIdentifiers; -// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) -begin:function begin(condition) { - this.conditionStack.push(condition); - }, +var numeric = /^[0-9]+$/; +function compareIdentifiers(a, b) { + var anum = numeric.test(a); + var bnum = numeric.test(b); -// pop the previously active lexer condition state off the condition stack -popState:function popState() { - var n = this.conditionStack.length - 1; - if (n > 0) { - return this.conditionStack.pop(); - } else { - return this.conditionStack[0]; - } - }, + if (anum && bnum) { + a = +a; + b = +b; + } -// produce the lexer rule set which is active for the currently active lexer condition state -_currentRules:function _currentRules() { - if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { - return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; - } else { - return this.conditions["INITIAL"].rules; - } - }, + return (anum && !bnum) ? -1 : + (bnum && !anum) ? 1 : + a < b ? -1 : + a > b ? 1 : + 0; +} -// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available -topState:function topState(n) { - n = this.conditionStack.length - 1 - Math.abs(n || 0); - if (n >= 0) { - return this.conditionStack[n]; - } else { - return "INITIAL"; - } - }, +exports.rcompareIdentifiers = rcompareIdentifiers; +function rcompareIdentifiers(a, b) { + return compareIdentifiers(b, a); +} -// alias for begin(condition) -pushState:function pushState(condition) { - this.begin(condition); - }, +exports.major = major; +function major(a, loose) { + return new SemVer(a, loose).major; +} -// return the number of states currently on the stack -stateStackSize:function stateStackSize() { - return this.conditionStack.length; - }, -options: {}, -performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { -var YYSTATE=YY_START; -switch($avoiding_name_collisions) { -case 0:return 5 -break; -case 1:/* skip whitespace */ -break; -case 2:return 8 -break; -case 3:return 16 -break; -case 4:return 17 -break; -case 5:return 11 -break; -case 6:return 10 -break; -case 7:return 9 -break; -case 8:return 14 -break; -case 9:return 15 +exports.minor = minor; +function minor(a, loose) { + return new SemVer(a, loose).minor; +} + +exports.patch = patch; +function patch(a, loose) { + return new SemVer(a, loose).patch; +} + +exports.compare = compare; +function compare(a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)); +} + +exports.compareLoose = compareLoose; +function compareLoose(a, b) { + return compare(a, b, true); +} + +exports.rcompare = rcompare; +function rcompare(a, b, loose) { + return compare(b, a, loose); +} + +exports.sort = sort; +function sort(list, loose) { + return list.sort(function(a, b) { + return exports.compare(a, b, loose); + }); +} + +exports.rsort = rsort; +function rsort(list, loose) { + return list.sort(function(a, b) { + return exports.rcompare(a, b, loose); + }); +} + +exports.gt = gt; +function gt(a, b, loose) { + return compare(a, b, loose) > 0; +} + +exports.lt = lt; +function lt(a, b, loose) { + return compare(a, b, loose) < 0; +} + +exports.eq = eq; +function eq(a, b, loose) { + return compare(a, b, loose) === 0; +} + +exports.neq = neq; +function neq(a, b, loose) { + return compare(a, b, loose) !== 0; +} + +exports.gte = gte; +function gte(a, b, loose) { + return compare(a, b, loose) >= 0; +} + +exports.lte = lte; +function lte(a, b, loose) { + return compare(a, b, loose) <= 0; +} + +exports.cmp = cmp; +function cmp(a, op, b, loose) { + var ret; + switch (op) { + case '===': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a === b; + break; + case '!==': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a !== b; + break; + case '': case '=': case '==': ret = eq(a, b, loose); break; + case '!=': ret = neq(a, b, loose); break; + case '>': ret = gt(a, b, loose); break; + case '>=': ret = gte(a, b, loose); break; + case '<': ret = lt(a, b, loose); break; + case '<=': ret = lte(a, b, loose); break; + default: throw new TypeError('Invalid operator: ' + op); + } + return ret; +} + +exports.Comparator = Comparator; +function Comparator(comp, loose) { + if (comp instanceof Comparator) { + if (comp.loose === loose) + return comp; + else + comp = comp.value; + } + + if (!(this instanceof Comparator)) + return new Comparator(comp, loose); + + debug('comparator', comp, loose); + this.loose = loose; + this.parse(comp); + + if (this.semver === ANY) + this.value = ''; + else + this.value = this.operator + this.semver.version; + + debug('comp', this); +} + +var ANY = {}; +Comparator.prototype.parse = function(comp) { + var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var m = comp.match(r); + + if (!m) + throw new TypeError('Invalid comparator: ' + comp); + + this.operator = m[1]; + if (this.operator === '=') + this.operator = ''; + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) + this.semver = ANY; + else + this.semver = new SemVer(m[2], this.loose); +}; + +Comparator.prototype.toString = function() { + return this.value; +}; + +Comparator.prototype.test = function(version) { + debug('Comparator.test', version, this.loose); + + if (this.semver === ANY) + return true; + + if (typeof version === 'string') + version = new SemVer(version, this.loose); + + return cmp(version, this.operator, this.semver, this.loose); +}; + +Comparator.prototype.intersects = function(comp, loose) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required'); + } + + var rangeTmp; + + if (this.operator === '') { + rangeTmp = new Range(comp.value, loose); + return satisfies(this.value, rangeTmp, loose); + } else if (comp.operator === '') { + rangeTmp = new Range(this.value, loose); + return satisfies(comp.semver, rangeTmp, loose); + } + + var sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>'); + var sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<'); + var sameSemVer = this.semver.version === comp.semver.version; + var differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<='); + var oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, loose) && + ((this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<')); + var oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, loose) && + ((this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>')); + + return sameDirectionIncreasing || sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; +}; + + +exports.Range = Range; +function Range(range, loose) { + if (range instanceof Range) { + if (range.loose === loose) { + return range; + } else { + return new Range(range.raw, loose); + } + } + + if (range instanceof Comparator) { + return new Range(range.value, loose); + } + + if (!(this instanceof Range)) + return new Range(range, loose); + + this.loose = loose; + + // First, split based on boolean or || + this.raw = range; + this.set = range.split(/\s*\|\|\s*/).map(function(range) { + return this.parseRange(range.trim()); + }, this).filter(function(c) { + // throw out any that are not relevant for whatever reason + return c.length; + }); + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range); + } + + this.format(); +} + +Range.prototype.format = function() { + this.range = this.set.map(function(comps) { + return comps.join(' ').trim(); + }).join('||').trim(); + return this.range; +}; + +Range.prototype.toString = function() { + return this.range; +}; + +Range.prototype.parseRange = function(range) { + var loose = this.loose; + range = range.trim(); + debug('range', range, loose); + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; + range = range.replace(hr, hyphenReplace); + debug('hyphen replace', range); + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); + debug('comparator trim', range, re[COMPARATORTRIM]); + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace); + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace); + + // normalize spaces + range = range.split(/\s+/).join(' '); + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var set = range.split(' ').map(function(comp) { + return parseComparator(comp, loose); + }).join(' ').split(/\s+/); + if (this.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function(comp) { + return !!comp.match(compRe); + }); + } + set = set.map(function(comp) { + return new Comparator(comp, loose); + }); + + return set; +}; + +Range.prototype.intersects = function(range, loose) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required'); + } + + return this.set.some(function(thisComparators) { + return thisComparators.every(function(thisComparator) { + return range.set.some(function(rangeComparators) { + return rangeComparators.every(function(rangeComparator) { + return thisComparator.intersects(rangeComparator, loose); + }); + }); + }); + }); +}; + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators; +function toComparators(range, loose) { + return new Range(range, loose).set.map(function(comp) { + return comp.map(function(c) { + return c.value; + }).join(' ').trim().split(' '); + }); +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator(comp, loose) { + debug('comp', comp); + comp = replaceCarets(comp, loose); + debug('caret', comp); + comp = replaceTildes(comp, loose); + debug('tildes', comp); + comp = replaceXRanges(comp, loose); + debug('xrange', comp); + comp = replaceStars(comp, loose); + debug('stars', comp); + return comp; +} + +function isX(id) { + return !id || id.toLowerCase() === 'x' || id === '*'; +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceTilde(comp, loose); + }).join(' '); +} + +function replaceTilde(comp, loose) { + var r = loose ? re[TILDELOOSE] : re[TILDE]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + else if (isX(p)) + // ~1.2 == >=1.2.0 <1.3.0 + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + else if (pr) { + debug('replaceTilde pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0'; + + debug('tilde return', ret); + return ret; + }); +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceCaret(comp, loose); + }).join(' '); +} + +function replaceCaret(comp, loose) { + debug('caret', comp, loose); + var r = loose ? re[CARETLOOSE] : re[CARET]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + else if (isX(p)) { + if (M === '0') + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + else + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; + } else if (pr) { + debug('replaceCaret pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + if (M === '0') { + if (m === '0') + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + m + '.' + (+p + 1); + else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + (+M + 1) + '.0.0'; + } else { + debug('no pr'); + if (M === '0') { + if (m === '0') + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + m + '.' + (+p + 1); + else + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + ret = '>=' + M + '.' + m + '.' + p + + ' <' + (+M + 1) + '.0.0'; + } + + debug('caret return', ret); + return ret; + }); +} + +function replaceXRanges(comp, loose) { + debug('replaceXRanges', comp, loose); + return comp.split(/\s+/).map(function(comp) { + return replaceXRange(comp, loose); + }).join(' '); +} + +function replaceXRange(comp, loose) { + comp = comp.trim(); + var r = loose ? re[XRANGELOOSE] : re[XRANGE]; + return comp.replace(r, function(ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr); + var xM = isX(M); + var xm = xM || isX(m); + var xp = xm || isX(p); + var anyX = xp; + + if (gtlt === '=' && anyX) + gtlt = ''; + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0'; + } else { + // nothing is forbidden + ret = '*'; + } + } else if (gtlt && anyX) { + // replace X with 0 + if (xm) + m = 0; + if (xp) + p = 0; + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + // >1.2.3 => >= 1.2.4 + gtlt = '>='; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else if (xp) { + m = +m + 1; + p = 0; + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<'; + if (xm) + M = +M + 1; + else + m = +m + 1; + } + + ret = gtlt + M + '.' + m + '.' + p; + } else if (xm) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + } else if (xp) { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + } + + debug('xRange return', ret); + + return ret; + }); +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars(comp, loose) { + debug('replaceStars', comp, loose); + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], ''); +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +function hyphenReplace($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + + if (isX(fM)) + from = ''; + else if (isX(fm)) + from = '>=' + fM + '.0.0'; + else if (isX(fp)) + from = '>=' + fM + '.' + fm + '.0'; + else + from = '>=' + from; + + if (isX(tM)) + to = ''; + else if (isX(tm)) + to = '<' + (+tM + 1) + '.0.0'; + else if (isX(tp)) + to = '<' + tM + '.' + (+tm + 1) + '.0'; + else if (tpr) + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; + else + to = '<=' + to; + + return (from + ' ' + to).trim(); +} + + +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function(version) { + if (!version) + return false; + + if (typeof version === 'string') + version = new SemVer(version, this.loose); + + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version)) + return true; + } + return false; +}; + +function testSet(set, version) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) + return false; + } + + if (version.prerelease.length) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (var i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === ANY) + continue; + + if (set[i].semver.prerelease.length > 0) { + var allowed = set[i].semver; + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) + return true; + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false; + } + + return true; +} + +exports.satisfies = satisfies; +function satisfies(version, range, loose) { + try { + range = new Range(range, loose); + } catch (er) { + return false; + } + return range.test(version); +} + +exports.maxSatisfying = maxSatisfying; +function maxSatisfying(versions, range, loose) { + var max = null; + var maxSV = null; + try { + var rangeObj = new Range(range, loose); + } catch (er) { + return null; + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { // satisfies(v, range, loose) + if (!max || maxSV.compare(v) === -1) { // compare(max, v, true) + max = v; + maxSV = new SemVer(max, loose); + } + } + }) + return max; +} + +exports.minSatisfying = minSatisfying; +function minSatisfying(versions, range, loose) { + var min = null; + var minSV = null; + try { + var rangeObj = new Range(range, loose); + } catch (er) { + return null; + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { // satisfies(v, range, loose) + if (!min || minSV.compare(v) === 1) { // compare(min, v, true) + min = v; + minSV = new SemVer(min, loose); + } + } + }) + return min; +} + +exports.validRange = validRange; +function validRange(range, loose) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, loose).range || '*'; + } catch (er) { + return null; + } +} + +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr; +function ltr(version, range, loose) { + return outside(version, range, '<', loose); +} + +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr; +function gtr(version, range, loose) { + return outside(version, range, '>', loose); +} + +exports.outside = outside; +function outside(version, range, hilo, loose) { + version = new SemVer(version, loose); + range = new Range(range, loose); + + var gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case '>': + gtfn = gt; + ltefn = lte; + ltfn = lt; + comp = '>'; + ecomp = '>='; + break; + case '<': + gtfn = lt; + ltefn = gte; + ltfn = gt; + comp = '<'; + ecomp = '<='; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, loose)) { + return false; + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i]; + + var high = null; + var low = null; + + comparators.forEach(function(comparator) { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, loose)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, loose)) { + low = comparator; + } + }); + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false; + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; +} + +exports.prerelease = prerelease; +function prerelease(version, loose) { + var parsed = parse(version, loose); + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; +} + +exports.intersects = intersects; +function intersects(r1, r2, loose) { + r1 = new Range(r1, loose) + r2 = new Range(r2, loose) + return r1.intersects(r2) +} + + +/***/ }), +/* 76 */ +/***/ (function(module, exports, __webpack_require__) { + +var parse = __webpack_require__(77); +var correct = __webpack_require__(79); + +var genericWarning = ( + 'license should be ' + + 'a valid SPDX license expression (without "LicenseRef"), ' + + '"UNLICENSED", or ' + + '"SEE LICENSE IN "' +); + +var fileReferenceRE = /^SEE LICEN[CS]E IN (.+)$/; + +function startsWith(prefix, string) { + return string.slice(0, prefix.length) === prefix; +} + +function usesLicenseRef(ast) { + if (ast.hasOwnProperty('license')) { + var license = ast.license; + return ( + startsWith('LicenseRef', license) || + startsWith('DocumentRef', license) + ); + } else { + return ( + usesLicenseRef(ast.left) || + usesLicenseRef(ast.right) + ); + } +} + +module.exports = function(argument) { + var ast; + + try { + ast = parse(argument); + } catch (e) { + var match + if ( + argument === 'UNLICENSED' || + argument === 'UNLICENCED' + ) { + return { + validForOldPackages: true, + validForNewPackages: true, + unlicensed: true + }; + } else if (match = fileReferenceRE.exec(argument)) { + return { + validForOldPackages: true, + validForNewPackages: true, + inFile: match[1] + }; + } else { + var result = { + validForOldPackages: false, + validForNewPackages: false, + warnings: [genericWarning] + }; + var corrected = correct(argument); + if (corrected) { + result.warnings.push( + 'license is similar to the valid expression "' + corrected + '"' + ); + } + return result; + } + } + + if (usesLicenseRef(ast)) { + return { + validForNewPackages: false, + validForOldPackages: false, + spdx: true, + warnings: [genericWarning] + }; + } else { + return { + validForNewPackages: true, + validForOldPackages: true, + spdx: true + }; + } +}; + + +/***/ }), +/* 77 */ +/***/ (function(module, exports, __webpack_require__) { + +var parser = __webpack_require__(78).parser + +module.exports = function (argument) { + return parser.parse(argument) +} + + +/***/ }), +/* 78 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */ +/* + Returns a Parser object of the following structure: + + Parser: { + yy: {} + } + + Parser.prototype: { + yy: {}, + trace: function(), + symbols_: {associative list: name ==> number}, + terminals_: {associative list: number ==> name}, + productions_: [...], + performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), + table: [...], + defaultActions: {...}, + parseError: function(str, hash), + parse: function(input), + + lexer: { + EOF: 1, + parseError: function(str, hash), + setInput: function(input), + input: function(), + unput: function(str), + more: function(), + less: function(n), + pastInput: function(), + upcomingInput: function(), + showPosition: function(), + test_match: function(regex_match_array, rule_index), + next: function(), + lex: function(), + begin: function(condition), + popState: function(), + _currentRules: function(), + topState: function(), + pushState: function(condition), + + options: { + ranges: boolean (optional: true ==> token location info will include a .range[] member) + flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) + backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) + }, + + performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), + rules: [...], + conditions: {associative list: name ==> set}, + } + } + + + token location info (@$, _$, etc.): { + first_line: n, + last_line: n, + first_column: n, + last_column: n, + range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) + } + + + the parseError function receives a 'hash' object with these members for lexer and parser errors: { + text: (matched text) + token: (the produced terminal token, if any) + line: (yylineno) + } + while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { + loc: (yylloc) + expected: (string describing the set of expected tokens) + recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) + } +*/ +var spdxparse = (function(){ +var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,6],$V2=[1,7],$V3=[1,4],$V4=[1,9],$V5=[1,10],$V6=[5,14,15,17],$V7=[5,12,14,15,17]; +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"start":3,"expression":4,"EOS":5,"simpleExpression":6,"LICENSE":7,"PLUS":8,"LICENSEREF":9,"DOCUMENTREF":10,"COLON":11,"WITH":12,"EXCEPTION":13,"AND":14,"OR":15,"OPEN":16,"CLOSE":17,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"EOS",7:"LICENSE",8:"PLUS",9:"LICENSEREF",10:"DOCUMENTREF",11:"COLON",12:"WITH",13:"EXCEPTION",14:"AND",15:"OR",16:"OPEN",17:"CLOSE"}, +productions_: [0,[3,2],[6,1],[6,2],[6,1],[6,3],[4,1],[4,3],[4,3],[4,3],[4,3]], +performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { +/* this == yyval */ + +var $0 = $$.length - 1; +switch (yystate) { +case 1: +return this.$ = $$[$0-1] +break; +case 2: case 4: case 5: +this.$ = {license: yytext} +break; +case 3: +this.$ = {license: $$[$0-1], plus: true} +break; +case 6: +this.$ = $$[$0] +break; +case 7: +this.$ = {exception: $$[$0]} +this.$.license = $$[$0-2].license +if ($$[$0-2].hasOwnProperty('plus')) { + this.$.plus = $$[$0-2].plus +} +break; +case 8: +this.$ = {conjunction: 'and', left: $$[$0-2], right: $$[$0]} +break; +case 9: +this.$ = {conjunction: 'or', left: $$[$0-2], right: $$[$0]} +break; +case 10: +this.$ = $$[$0-1] +break; +} +}, +table: [{3:1,4:2,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{1:[3]},{5:[1,8],14:$V4,15:$V5},o($V6,[2,6],{12:[1,11]}),{4:12,6:3,7:$V0,9:$V1,10:$V2,16:$V3},o($V7,[2,2],{8:[1,13]}),o($V7,[2,4]),{11:[1,14]},{1:[2,1]},{4:15,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{4:16,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{13:[1,17]},{14:$V4,15:$V5,17:[1,18]},o($V7,[2,3]),{9:[1,19]},o($V6,[2,8]),o([5,15,17],[2,9],{14:$V4}),o($V6,[2,7]),o($V6,[2,10]),o($V7,[2,5])], +defaultActions: {8:[2,1]}, +parseError: function parseError(str, hash) { + if (hash.recoverable) { + this.trace(str); + } else { + function _parseError (msg, hash) { + this.message = msg; + this.hash = hash; + } + _parseError.prototype = Error; + + throw new _parseError(str, hash); + } +}, +parse: function parse(input) { + var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + var args = lstack.slice.call(arguments, 1); + var lexer = Object.create(this.lexer); + var sharedState = { yy: {} }; + for (var k in this.yy) { + if (Object.prototype.hasOwnProperty.call(this.yy, k)) { + sharedState.yy[k] = this.yy[k]; + } + } + lexer.setInput(input, sharedState.yy); + sharedState.yy.lexer = lexer; + sharedState.yy.parser = this; + if (typeof lexer.yylloc == 'undefined') { + lexer.yylloc = {}; + } + var yyloc = lexer.yylloc; + lstack.push(yyloc); + var ranges = lexer.options && lexer.options.ranges; + if (typeof sharedState.yy.parseError === 'function') { + this.parseError = sharedState.yy.parseError; + } else { + this.parseError = Object.getPrototypeOf(this).parseError; + } + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + _token_stack: + var lex = function () { + var token; + token = lexer.lex() || EOF; + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + }; + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == 'undefined') { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === 'undefined' || !action.length || !action[0]) { + var errStr = ''; + expected = []; + for (p in table[state]) { + if (this.terminals_[p] && p > TERROR) { + expected.push('\'' + this.terminals_[p] + '\''); + } + } + if (lexer.showPosition) { + errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; + } else { + errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); + } + this.parseError(errStr, { + text: lexer.match, + token: this.terminals_[symbol] || symbol, + line: lexer.yylineno, + loc: yyloc, + expected: expected + }); + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(lexer.yytext); + lstack.push(lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = lexer.yyleng; + yytext = lexer.yytext; + yylineno = lexer.yylineno; + yyloc = lexer.yylloc; + if (recovering > 0) { + recovering--; + } + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = { + first_line: lstack[lstack.length - (len || 1)].first_line, + last_line: lstack[lstack.length - 1].last_line, + first_column: lstack[lstack.length - (len || 1)].first_column, + last_column: lstack[lstack.length - 1].last_column + }; + if (ranges) { + yyval._$.range = [ + lstack[lstack.length - (len || 1)].range[0], + lstack[lstack.length - 1].range[1] + ]; + } + r = this.performAction.apply(yyval, [ + yytext, + yyleng, + yylineno, + sharedState.yy, + action[1], + vstack, + lstack + ].concat(args)); + if (typeof r !== 'undefined') { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; +}}; +/* generated by jison-lex 0.3.4 */ +var lexer = (function(){ +var lexer = ({ + +EOF:1, + +parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + +// resets the lexer, sets new input +setInput:function (input, yy) { + this.yy = yy || this.yy || {}; + this._input = input; + this._more = this._backtrack = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = { + first_line: 1, + first_column: 0, + last_line: 1, + last_column: 0 + }; + if (this.options.ranges) { + this.yylloc.range = [0,0]; + } + this.offset = 0; + return this; + }, + +// consumes and returns one char from the input +input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) { + this.yylloc.range[1]++; + } + + this._input = this._input.slice(1); + return ch; + }, + +// unshifts one char (or a string) into the input +unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length - len); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length - 1); + this.matched = this.matched.substr(0, this.matched.length - 1); + + if (lines.length - 1) { + this.yylineno -= lines.length - 1; + } + var r = this.yylloc.range; + + this.yylloc = { + first_line: this.yylloc.first_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + + oldLines[oldLines.length - lines.length].length - lines[0].length : + this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + this.yyleng = this.yytext.length; + return this; + }, + +// When called from action, caches matched text and appends it on next action +more:function () { + this._more = true; + return this; + }, + +// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. +reject:function () { + if (this.options.backtrack_lexer) { + this._backtrack = true; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { + text: "", + token: null, + line: this.yylineno + }); + + } + return this; + }, + +// retain first n characters of the match +less:function (n) { + this.unput(this.match.slice(n)); + }, + +// displays already matched input, i.e. for error messages +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, + +// displays upcoming input, i.e. for error messages +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); + }, + +// displays the character position where the lexing error occurred, i.e. for error messages +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c + "^"; + }, + +// test the lexed token: return FALSE when not a match, otherwise return token +test_match:function (match, indexed_rule) { + var token, + lines, + backup; + + if (this.options.backtrack_lexer) { + // save context + backup = { + yylineno: this.yylineno, + yylloc: { + first_line: this.yylloc.first_line, + last_line: this.last_line, + first_column: this.yylloc.first_column, + last_column: this.yylloc.last_column + }, + yytext: this.yytext, + match: this.match, + matches: this.matches, + matched: this.matched, + yyleng: this.yyleng, + offset: this.offset, + _more: this._more, + _input: this._input, + yy: this.yy, + conditionStack: this.conditionStack.slice(0), + done: this.done + }; + if (this.options.ranges) { + backup.yylloc.range = this.yylloc.range.slice(0); + } + } + + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno += lines.length; + } + this.yylloc = { + first_line: this.yylloc.last_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.last_column, + last_column: lines ? + lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : + this.yylloc.last_column + match[0].length + }; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._backtrack = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); + if (this.done && this._input) { + this.done = false; + } + if (token) { + return token; + } else if (this._backtrack) { + // recover context + for (var k in backup) { + this[k] = backup[k]; + } + return false; // rule action called reject() implying the next rule should be tested instead. + } + return false; + }, + +// return next match in input +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) { + this.done = true; + } + + var token, + match, + tempMatch, + index; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i = 0; i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (this.options.backtrack_lexer) { + token = this.test_match(tempMatch, rules[i]); + if (token !== false) { + return token; + } else if (this._backtrack) { + match = false; + continue; // rule action called reject() implying a rule MISmatch. + } else { + // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) + return false; + } + } else if (!this.options.flex) { + break; + } + } + } + if (match) { + token = this.test_match(match, rules[index]); + if (token !== false) { + return token; + } + // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) + return false; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { + text: "", + token: null, + line: this.yylineno + }); + } + }, + +// return next match that has a token +lex:function lex() { + var r = this.next(); + if (r) { + return r; + } else { + return this.lex(); + } + }, + +// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) +begin:function begin(condition) { + this.conditionStack.push(condition); + }, + +// pop the previously active lexer condition state off the condition stack +popState:function popState() { + var n = this.conditionStack.length - 1; + if (n > 0) { + return this.conditionStack.pop(); + } else { + return this.conditionStack[0]; + } + }, + +// produce the lexer rule set which is active for the currently active lexer condition state +_currentRules:function _currentRules() { + if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { + return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; + } else { + return this.conditions["INITIAL"].rules; + } + }, + +// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available +topState:function topState(n) { + n = this.conditionStack.length - 1 - Math.abs(n || 0); + if (n >= 0) { + return this.conditionStack[n]; + } else { + return "INITIAL"; + } + }, + +// alias for begin(condition) +pushState:function pushState(condition) { + this.begin(condition); + }, + +// return the number of states currently on the stack +stateStackSize:function stateStackSize() { + return this.conditionStack.length; + }, +options: {}, +performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { +var YYSTATE=YY_START; +switch($avoiding_name_collisions) { +case 0:return 5 +break; +case 1:/* skip whitespace */ +break; +case 2:return 8 +break; +case 3:return 16 +break; +case 4:return 17 +break; +case 5:return 11 +break; +case 6:return 10 +break; +case 7:return 9 +break; +case 8:return 14 +break; +case 9:return 15 break; case 10:return 12 break; @@ -11923,7601 +13386,12613 @@ break; case 364:return 7 break; } -}, -rules: [/^(?:$)/,/^(?:\s+)/,/^(?:\+)/,/^(?:\()/,/^(?:\))/,/^(?::)/,/^(?:DocumentRef-([0-9A-Za-z-+.]+))/,/^(?:LicenseRef-([0-9A-Za-z-+.]+))/,/^(?:AND)/,/^(?:OR)/,/^(?:WITH)/,/^(?:BSD-3-Clause-No-Nuclear-License-2014)/,/^(?:BSD-3-Clause-No-Nuclear-Warranty)/,/^(?:GPL-2\.0-with-classpath-exception)/,/^(?:GPL-3\.0-with-autoconf-exception)/,/^(?:GPL-2\.0-with-autoconf-exception)/,/^(?:BSD-3-Clause-No-Nuclear-License)/,/^(?:MPL-2\.0-no-copyleft-exception)/,/^(?:GPL-2\.0-with-bison-exception)/,/^(?:GPL-2\.0-with-font-exception)/,/^(?:GPL-2\.0-with-GCC-exception)/,/^(?:CNRI-Python-GPL-Compatible)/,/^(?:GPL-3\.0-with-GCC-exception)/,/^(?:BSD-3-Clause-Attribution)/,/^(?:Classpath-exception-2\.0)/,/^(?:WxWindows-exception-3\.1)/,/^(?:freertos-exception-2\.0)/,/^(?:Autoconf-exception-3\.0)/,/^(?:i2p-gpl-java-exception)/,/^(?:gnu-javamail-exception)/,/^(?:Nokia-Qt-exception-1\.1)/,/^(?:Autoconf-exception-2\.0)/,/^(?:BSD-2-Clause-FreeBSD)/,/^(?:u-boot-exception-2\.0)/,/^(?:zlib-acknowledgement)/,/^(?:Bison-exception-2\.2)/,/^(?:BSD-2-Clause-NetBSD)/,/^(?:CLISP-exception-2\.0)/,/^(?:eCos-exception-2\.0)/,/^(?:BSD-3-Clause-Clear)/,/^(?:Font-exception-2\.0)/,/^(?:FLTK-exception-2\.0)/,/^(?:GCC-exception-2\.0)/,/^(?:Qwt-exception-1\.0)/,/^(?:Libtool-exception)/,/^(?:BSD-3-Clause-LBNL)/,/^(?:GCC-exception-3\.1)/,/^(?:Artistic-1\.0-Perl)/,/^(?:Artistic-1\.0-cl8)/,/^(?:CC-BY-NC-SA-2\.5)/,/^(?:MIT-advertising)/,/^(?:BSD-Source-Code)/,/^(?:CC-BY-NC-SA-4\.0)/,/^(?:LiLiQ-Rplus-1\.1)/,/^(?:CC-BY-NC-SA-3\.0)/,/^(?:BSD-4-Clause-UC)/,/^(?:CC-BY-NC-SA-2\.0)/,/^(?:CC-BY-NC-SA-1\.0)/,/^(?:CC-BY-NC-ND-4\.0)/,/^(?:CC-BY-NC-ND-3\.0)/,/^(?:CC-BY-NC-ND-2\.5)/,/^(?:CC-BY-NC-ND-2\.0)/,/^(?:CC-BY-NC-ND-1\.0)/,/^(?:LZMA-exception)/,/^(?:BitTorrent-1\.1)/,/^(?:CrystalStacker)/,/^(?:FLTK-exception)/,/^(?:SugarCRM-1\.1\.3)/,/^(?:BSD-Protection)/,/^(?:BitTorrent-1\.0)/,/^(?:HaskellReport)/,/^(?:Interbase-1\.0)/,/^(?:StandardML-NJ)/,/^(?:mif-exception)/,/^(?:Frameworx-1\.0)/,/^(?:389-exception)/,/^(?:CC-BY-NC-2\.0)/,/^(?:CC-BY-NC-2\.5)/,/^(?:CC-BY-NC-3\.0)/,/^(?:CC-BY-NC-4\.0)/,/^(?:W3C-19980720)/,/^(?:CC-BY-SA-1\.0)/,/^(?:CC-BY-SA-2\.0)/,/^(?:CC-BY-SA-2\.5)/,/^(?:CC-BY-ND-2\.0)/,/^(?:CC-BY-SA-4\.0)/,/^(?:CC-BY-SA-3\.0)/,/^(?:Artistic-1\.0)/,/^(?:Artistic-2\.0)/,/^(?:CC-BY-ND-2\.5)/,/^(?:CC-BY-ND-3\.0)/,/^(?:CC-BY-ND-4\.0)/,/^(?:CC-BY-ND-1\.0)/,/^(?:BSD-4-Clause)/,/^(?:BSD-3-Clause)/,/^(?:BSD-2-Clause)/,/^(?:CC-BY-NC-1\.0)/,/^(?:bzip2-1\.0\.6)/,/^(?:Unicode-TOU)/,/^(?:CNRI-Jython)/,/^(?:ImageMagick)/,/^(?:Adobe-Glyph)/,/^(?:CUA-OPL-1\.0)/,/^(?:OLDAP-2\.2\.2)/,/^(?:LiLiQ-R-1\.1)/,/^(?:bzip2-1\.0\.5)/,/^(?:LiLiQ-P-1\.1)/,/^(?:OLDAP-2\.0\.1)/,/^(?:OLDAP-2\.2\.1)/,/^(?:CNRI-Python)/,/^(?:XFree86-1\.1)/,/^(?:OSET-PL-2\.1)/,/^(?:Apache-2\.0)/,/^(?:Watcom-1\.0)/,/^(?:PostgreSQL)/,/^(?:Python-2\.0)/,/^(?:RHeCos-1\.1)/,/^(?:EUDatagrid)/,/^(?:Spencer-99)/,/^(?:Intel-ACPI)/,/^(?:CECILL-1\.0)/,/^(?:CECILL-1\.1)/,/^(?:JasPer-2\.0)/,/^(?:CECILL-2\.0)/,/^(?:CECILL-2\.1)/,/^(?:gSOAP-1\.3b)/,/^(?:Spencer-94)/,/^(?:Apache-1\.1)/,/^(?:Spencer-86)/,/^(?:Apache-1\.0)/,/^(?:ClArtistic)/,/^(?:TORQUE-1\.1)/,/^(?:CATOSL-1\.1)/,/^(?:Adobe-2006)/,/^(?:Zimbra-1\.4)/,/^(?:Zimbra-1\.3)/,/^(?:Condor-1\.1)/,/^(?:CC-BY-3\.0)/,/^(?:CC-BY-2\.5)/,/^(?:OLDAP-2\.4)/,/^(?:SGI-B-1\.1)/,/^(?:SISSL-1\.2)/,/^(?:SGI-B-1\.0)/,/^(?:OLDAP-2\.3)/,/^(?:CC-BY-4\.0)/,/^(?:Crossword)/,/^(?:SimPL-2\.0)/,/^(?:OLDAP-2\.2)/,/^(?:OLDAP-2\.1)/,/^(?:ErlPL-1\.1)/,/^(?:LPPL-1\.3a)/,/^(?:LPPL-1\.3c)/,/^(?:OLDAP-2\.0)/,/^(?:Leptonica)/,/^(?:CPOL-1\.02)/,/^(?:OLDAP-1\.4)/,/^(?:OLDAP-1\.3)/,/^(?:CC-BY-2\.0)/,/^(?:Unlicense)/,/^(?:OLDAP-2\.8)/,/^(?:OLDAP-1\.2)/,/^(?:MakeIndex)/,/^(?:OLDAP-2\.7)/,/^(?:OLDAP-1\.1)/,/^(?:Sleepycat)/,/^(?:D-FSL-1\.0)/,/^(?:CC-BY-1\.0)/,/^(?:OLDAP-2\.6)/,/^(?:WXwindows)/,/^(?:NPOSL-3\.0)/,/^(?:FreeImage)/,/^(?:SGI-B-2\.0)/,/^(?:OLDAP-2\.5)/,/^(?:Beerware)/,/^(?:Newsletr)/,/^(?:NBPL-1\.0)/,/^(?:NASA-1\.3)/,/^(?:NLOD-1\.0)/,/^(?:AGPL-1\.0)/,/^(?:OCLC-2\.0)/,/^(?:ODbL-1\.0)/,/^(?:PDDL-1\.0)/,/^(?:Motosoto)/,/^(?:Afmparse)/,/^(?:ANTLR-PD)/,/^(?:LPL-1\.02)/,/^(?:Abstyles)/,/^(?:eCos-2\.0)/,/^(?:APSL-1\.0)/,/^(?:LPPL-1\.2)/,/^(?:LPPL-1\.1)/,/^(?:LPPL-1\.0)/,/^(?:APSL-1\.1)/,/^(?:APSL-2\.0)/,/^(?:Info-ZIP)/,/^(?:Zend-2\.0)/,/^(?:IBM-pibs)/,/^(?:LGPL-2\.0)/,/^(?:LGPL-3\.0)/,/^(?:LGPL-2\.1)/,/^(?:GFDL-1\.3)/,/^(?:PHP-3\.01)/,/^(?:GFDL-1\.2)/,/^(?:GFDL-1\.1)/,/^(?:AGPL-3\.0)/,/^(?:Giftware)/,/^(?:EUPL-1\.1)/,/^(?:RPSL-1\.0)/,/^(?:EUPL-1\.0)/,/^(?:MIT-enna)/,/^(?:CECILL-B)/,/^(?:diffmark)/,/^(?:CECILL-C)/,/^(?:CDDL-1\.0)/,/^(?:Sendmail)/,/^(?:CDDL-1\.1)/,/^(?:CPAL-1\.0)/,/^(?:APSL-1\.2)/,/^(?:NPL-1\.1)/,/^(?:AFL-1\.2)/,/^(?:Caldera)/,/^(?:AFL-2\.0)/,/^(?:FSFULLR)/,/^(?:AFL-2\.1)/,/^(?:VSL-1\.0)/,/^(?:VOSTROM)/,/^(?:UPL-1\.0)/,/^(?:Dotseqn)/,/^(?:CPL-1\.0)/,/^(?:dvipdfm)/,/^(?:EPL-1\.0)/,/^(?:OCCT-PL)/,/^(?:ECL-1\.0)/,/^(?:Latex2e)/,/^(?:ECL-2\.0)/,/^(?:GPL-1\.0)/,/^(?:GPL-2\.0)/,/^(?:GPL-3\.0)/,/^(?:AFL-3\.0)/,/^(?:LAL-1\.2)/,/^(?:LAL-1\.3)/,/^(?:EFL-1\.0)/,/^(?:EFL-2\.0)/,/^(?:gnuplot)/,/^(?:Aladdin)/,/^(?:LPL-1\.0)/,/^(?:libtiff)/,/^(?:Entessa)/,/^(?:AMDPLPA)/,/^(?:IPL-1\.0)/,/^(?:OPL-1\.0)/,/^(?:OSL-1\.0)/,/^(?:OSL-1\.1)/,/^(?:OSL-2\.0)/,/^(?:OSL-2\.1)/,/^(?:OSL-3\.0)/,/^(?:OpenSSL)/,/^(?:ZPL-2\.1)/,/^(?:PHP-3\.0)/,/^(?:ZPL-2\.0)/,/^(?:ZPL-1\.1)/,/^(?:CC0-1\.0)/,/^(?:SPL-1\.0)/,/^(?:psutils)/,/^(?:MPL-1\.0)/,/^(?:QPL-1\.0)/,/^(?:MPL-1\.1)/,/^(?:MPL-2\.0)/,/^(?:APL-1\.0)/,/^(?:RPL-1\.1)/,/^(?:RPL-1\.5)/,/^(?:MIT-CMU)/,/^(?:Multics)/,/^(?:Eurosym)/,/^(?:BSL-1\.0)/,/^(?:MIT-feh)/,/^(?:Saxpath)/,/^(?:Borceux)/,/^(?:OFL-1\.1)/,/^(?:OFL-1\.0)/,/^(?:AFL-1\.1)/,/^(?:YPL-1\.1)/,/^(?:YPL-1\.0)/,/^(?:NPL-1\.0)/,/^(?:iMatix)/,/^(?:mpich2)/,/^(?:APAFML)/,/^(?:Bahyph)/,/^(?:RSA-MD)/,/^(?:psfrag)/,/^(?:Plexus)/,/^(?:eGenix)/,/^(?:Glulxe)/,/^(?:SAX-PD)/,/^(?:Imlib2)/,/^(?:Wsuipa)/,/^(?:LGPLLR)/,/^(?:Libpng)/,/^(?:xinetd)/,/^(?:MITNFA)/,/^(?:NetCDF)/,/^(?:Naumen)/,/^(?:SMPPL)/,/^(?:Nunit)/,/^(?:FSFUL)/,/^(?:GL2PS)/,/^(?:SMLNJ)/,/^(?:Rdisc)/,/^(?:Noweb)/,/^(?:Nokia)/,/^(?:SISSL)/,/^(?:Qhull)/,/^(?:Intel)/,/^(?:Glide)/,/^(?:Xerox)/,/^(?:AMPAS)/,/^(?:WTFPL)/,/^(?:MS-PL)/,/^(?:XSkat)/,/^(?:MS-RL)/,/^(?:MirOS)/,/^(?:RSCPL)/,/^(?:TMate)/,/^(?:OGTSL)/,/^(?:FSFAP)/,/^(?:NCSA)/,/^(?:Zlib)/,/^(?:SCEA)/,/^(?:SNIA)/,/^(?:NGPL)/,/^(?:NOSL)/,/^(?:ADSL)/,/^(?:MTLL)/,/^(?:NLPL)/,/^(?:Ruby)/,/^(?:JSON)/,/^(?:Barr)/,/^(?:0BSD)/,/^(?:Xnet)/,/^(?:Cube)/,/^(?:curl)/,/^(?:DSDP)/,/^(?:Fair)/,/^(?:HPND)/,/^(?:TOSL)/,/^(?:IJG)/,/^(?:SWL)/,/^(?:Vim)/,/^(?:FTL)/,/^(?:ICU)/,/^(?:OML)/,/^(?:NRL)/,/^(?:DOC)/,/^(?:TCL)/,/^(?:W3C)/,/^(?:NTP)/,/^(?:IPA)/,/^(?:ISC)/,/^(?:X11)/,/^(?:AAL)/,/^(?:AML)/,/^(?:xpp)/,/^(?:Zed)/,/^(?:MIT)/,/^(?:Mup)/], -conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364],"inclusive":true}} -}); -return lexer; -})(); -parser.lexer = lexer; -function Parser () { - this.yy = {}; +}, +rules: [/^(?:$)/,/^(?:\s+)/,/^(?:\+)/,/^(?:\()/,/^(?:\))/,/^(?::)/,/^(?:DocumentRef-([0-9A-Za-z-+.]+))/,/^(?:LicenseRef-([0-9A-Za-z-+.]+))/,/^(?:AND)/,/^(?:OR)/,/^(?:WITH)/,/^(?:BSD-3-Clause-No-Nuclear-License-2014)/,/^(?:BSD-3-Clause-No-Nuclear-Warranty)/,/^(?:GPL-2\.0-with-classpath-exception)/,/^(?:GPL-3\.0-with-autoconf-exception)/,/^(?:GPL-2\.0-with-autoconf-exception)/,/^(?:BSD-3-Clause-No-Nuclear-License)/,/^(?:MPL-2\.0-no-copyleft-exception)/,/^(?:GPL-2\.0-with-bison-exception)/,/^(?:GPL-2\.0-with-font-exception)/,/^(?:GPL-2\.0-with-GCC-exception)/,/^(?:CNRI-Python-GPL-Compatible)/,/^(?:GPL-3\.0-with-GCC-exception)/,/^(?:BSD-3-Clause-Attribution)/,/^(?:Classpath-exception-2\.0)/,/^(?:WxWindows-exception-3\.1)/,/^(?:freertos-exception-2\.0)/,/^(?:Autoconf-exception-3\.0)/,/^(?:i2p-gpl-java-exception)/,/^(?:gnu-javamail-exception)/,/^(?:Nokia-Qt-exception-1\.1)/,/^(?:Autoconf-exception-2\.0)/,/^(?:BSD-2-Clause-FreeBSD)/,/^(?:u-boot-exception-2\.0)/,/^(?:zlib-acknowledgement)/,/^(?:Bison-exception-2\.2)/,/^(?:BSD-2-Clause-NetBSD)/,/^(?:CLISP-exception-2\.0)/,/^(?:eCos-exception-2\.0)/,/^(?:BSD-3-Clause-Clear)/,/^(?:Font-exception-2\.0)/,/^(?:FLTK-exception-2\.0)/,/^(?:GCC-exception-2\.0)/,/^(?:Qwt-exception-1\.0)/,/^(?:Libtool-exception)/,/^(?:BSD-3-Clause-LBNL)/,/^(?:GCC-exception-3\.1)/,/^(?:Artistic-1\.0-Perl)/,/^(?:Artistic-1\.0-cl8)/,/^(?:CC-BY-NC-SA-2\.5)/,/^(?:MIT-advertising)/,/^(?:BSD-Source-Code)/,/^(?:CC-BY-NC-SA-4\.0)/,/^(?:LiLiQ-Rplus-1\.1)/,/^(?:CC-BY-NC-SA-3\.0)/,/^(?:BSD-4-Clause-UC)/,/^(?:CC-BY-NC-SA-2\.0)/,/^(?:CC-BY-NC-SA-1\.0)/,/^(?:CC-BY-NC-ND-4\.0)/,/^(?:CC-BY-NC-ND-3\.0)/,/^(?:CC-BY-NC-ND-2\.5)/,/^(?:CC-BY-NC-ND-2\.0)/,/^(?:CC-BY-NC-ND-1\.0)/,/^(?:LZMA-exception)/,/^(?:BitTorrent-1\.1)/,/^(?:CrystalStacker)/,/^(?:FLTK-exception)/,/^(?:SugarCRM-1\.1\.3)/,/^(?:BSD-Protection)/,/^(?:BitTorrent-1\.0)/,/^(?:HaskellReport)/,/^(?:Interbase-1\.0)/,/^(?:StandardML-NJ)/,/^(?:mif-exception)/,/^(?:Frameworx-1\.0)/,/^(?:389-exception)/,/^(?:CC-BY-NC-2\.0)/,/^(?:CC-BY-NC-2\.5)/,/^(?:CC-BY-NC-3\.0)/,/^(?:CC-BY-NC-4\.0)/,/^(?:W3C-19980720)/,/^(?:CC-BY-SA-1\.0)/,/^(?:CC-BY-SA-2\.0)/,/^(?:CC-BY-SA-2\.5)/,/^(?:CC-BY-ND-2\.0)/,/^(?:CC-BY-SA-4\.0)/,/^(?:CC-BY-SA-3\.0)/,/^(?:Artistic-1\.0)/,/^(?:Artistic-2\.0)/,/^(?:CC-BY-ND-2\.5)/,/^(?:CC-BY-ND-3\.0)/,/^(?:CC-BY-ND-4\.0)/,/^(?:CC-BY-ND-1\.0)/,/^(?:BSD-4-Clause)/,/^(?:BSD-3-Clause)/,/^(?:BSD-2-Clause)/,/^(?:CC-BY-NC-1\.0)/,/^(?:bzip2-1\.0\.6)/,/^(?:Unicode-TOU)/,/^(?:CNRI-Jython)/,/^(?:ImageMagick)/,/^(?:Adobe-Glyph)/,/^(?:CUA-OPL-1\.0)/,/^(?:OLDAP-2\.2\.2)/,/^(?:LiLiQ-R-1\.1)/,/^(?:bzip2-1\.0\.5)/,/^(?:LiLiQ-P-1\.1)/,/^(?:OLDAP-2\.0\.1)/,/^(?:OLDAP-2\.2\.1)/,/^(?:CNRI-Python)/,/^(?:XFree86-1\.1)/,/^(?:OSET-PL-2\.1)/,/^(?:Apache-2\.0)/,/^(?:Watcom-1\.0)/,/^(?:PostgreSQL)/,/^(?:Python-2\.0)/,/^(?:RHeCos-1\.1)/,/^(?:EUDatagrid)/,/^(?:Spencer-99)/,/^(?:Intel-ACPI)/,/^(?:CECILL-1\.0)/,/^(?:CECILL-1\.1)/,/^(?:JasPer-2\.0)/,/^(?:CECILL-2\.0)/,/^(?:CECILL-2\.1)/,/^(?:gSOAP-1\.3b)/,/^(?:Spencer-94)/,/^(?:Apache-1\.1)/,/^(?:Spencer-86)/,/^(?:Apache-1\.0)/,/^(?:ClArtistic)/,/^(?:TORQUE-1\.1)/,/^(?:CATOSL-1\.1)/,/^(?:Adobe-2006)/,/^(?:Zimbra-1\.4)/,/^(?:Zimbra-1\.3)/,/^(?:Condor-1\.1)/,/^(?:CC-BY-3\.0)/,/^(?:CC-BY-2\.5)/,/^(?:OLDAP-2\.4)/,/^(?:SGI-B-1\.1)/,/^(?:SISSL-1\.2)/,/^(?:SGI-B-1\.0)/,/^(?:OLDAP-2\.3)/,/^(?:CC-BY-4\.0)/,/^(?:Crossword)/,/^(?:SimPL-2\.0)/,/^(?:OLDAP-2\.2)/,/^(?:OLDAP-2\.1)/,/^(?:ErlPL-1\.1)/,/^(?:LPPL-1\.3a)/,/^(?:LPPL-1\.3c)/,/^(?:OLDAP-2\.0)/,/^(?:Leptonica)/,/^(?:CPOL-1\.02)/,/^(?:OLDAP-1\.4)/,/^(?:OLDAP-1\.3)/,/^(?:CC-BY-2\.0)/,/^(?:Unlicense)/,/^(?:OLDAP-2\.8)/,/^(?:OLDAP-1\.2)/,/^(?:MakeIndex)/,/^(?:OLDAP-2\.7)/,/^(?:OLDAP-1\.1)/,/^(?:Sleepycat)/,/^(?:D-FSL-1\.0)/,/^(?:CC-BY-1\.0)/,/^(?:OLDAP-2\.6)/,/^(?:WXwindows)/,/^(?:NPOSL-3\.0)/,/^(?:FreeImage)/,/^(?:SGI-B-2\.0)/,/^(?:OLDAP-2\.5)/,/^(?:Beerware)/,/^(?:Newsletr)/,/^(?:NBPL-1\.0)/,/^(?:NASA-1\.3)/,/^(?:NLOD-1\.0)/,/^(?:AGPL-1\.0)/,/^(?:OCLC-2\.0)/,/^(?:ODbL-1\.0)/,/^(?:PDDL-1\.0)/,/^(?:Motosoto)/,/^(?:Afmparse)/,/^(?:ANTLR-PD)/,/^(?:LPL-1\.02)/,/^(?:Abstyles)/,/^(?:eCos-2\.0)/,/^(?:APSL-1\.0)/,/^(?:LPPL-1\.2)/,/^(?:LPPL-1\.1)/,/^(?:LPPL-1\.0)/,/^(?:APSL-1\.1)/,/^(?:APSL-2\.0)/,/^(?:Info-ZIP)/,/^(?:Zend-2\.0)/,/^(?:IBM-pibs)/,/^(?:LGPL-2\.0)/,/^(?:LGPL-3\.0)/,/^(?:LGPL-2\.1)/,/^(?:GFDL-1\.3)/,/^(?:PHP-3\.01)/,/^(?:GFDL-1\.2)/,/^(?:GFDL-1\.1)/,/^(?:AGPL-3\.0)/,/^(?:Giftware)/,/^(?:EUPL-1\.1)/,/^(?:RPSL-1\.0)/,/^(?:EUPL-1\.0)/,/^(?:MIT-enna)/,/^(?:CECILL-B)/,/^(?:diffmark)/,/^(?:CECILL-C)/,/^(?:CDDL-1\.0)/,/^(?:Sendmail)/,/^(?:CDDL-1\.1)/,/^(?:CPAL-1\.0)/,/^(?:APSL-1\.2)/,/^(?:NPL-1\.1)/,/^(?:AFL-1\.2)/,/^(?:Caldera)/,/^(?:AFL-2\.0)/,/^(?:FSFULLR)/,/^(?:AFL-2\.1)/,/^(?:VSL-1\.0)/,/^(?:VOSTROM)/,/^(?:UPL-1\.0)/,/^(?:Dotseqn)/,/^(?:CPL-1\.0)/,/^(?:dvipdfm)/,/^(?:EPL-1\.0)/,/^(?:OCCT-PL)/,/^(?:ECL-1\.0)/,/^(?:Latex2e)/,/^(?:ECL-2\.0)/,/^(?:GPL-1\.0)/,/^(?:GPL-2\.0)/,/^(?:GPL-3\.0)/,/^(?:AFL-3\.0)/,/^(?:LAL-1\.2)/,/^(?:LAL-1\.3)/,/^(?:EFL-1\.0)/,/^(?:EFL-2\.0)/,/^(?:gnuplot)/,/^(?:Aladdin)/,/^(?:LPL-1\.0)/,/^(?:libtiff)/,/^(?:Entessa)/,/^(?:AMDPLPA)/,/^(?:IPL-1\.0)/,/^(?:OPL-1\.0)/,/^(?:OSL-1\.0)/,/^(?:OSL-1\.1)/,/^(?:OSL-2\.0)/,/^(?:OSL-2\.1)/,/^(?:OSL-3\.0)/,/^(?:OpenSSL)/,/^(?:ZPL-2\.1)/,/^(?:PHP-3\.0)/,/^(?:ZPL-2\.0)/,/^(?:ZPL-1\.1)/,/^(?:CC0-1\.0)/,/^(?:SPL-1\.0)/,/^(?:psutils)/,/^(?:MPL-1\.0)/,/^(?:QPL-1\.0)/,/^(?:MPL-1\.1)/,/^(?:MPL-2\.0)/,/^(?:APL-1\.0)/,/^(?:RPL-1\.1)/,/^(?:RPL-1\.5)/,/^(?:MIT-CMU)/,/^(?:Multics)/,/^(?:Eurosym)/,/^(?:BSL-1\.0)/,/^(?:MIT-feh)/,/^(?:Saxpath)/,/^(?:Borceux)/,/^(?:OFL-1\.1)/,/^(?:OFL-1\.0)/,/^(?:AFL-1\.1)/,/^(?:YPL-1\.1)/,/^(?:YPL-1\.0)/,/^(?:NPL-1\.0)/,/^(?:iMatix)/,/^(?:mpich2)/,/^(?:APAFML)/,/^(?:Bahyph)/,/^(?:RSA-MD)/,/^(?:psfrag)/,/^(?:Plexus)/,/^(?:eGenix)/,/^(?:Glulxe)/,/^(?:SAX-PD)/,/^(?:Imlib2)/,/^(?:Wsuipa)/,/^(?:LGPLLR)/,/^(?:Libpng)/,/^(?:xinetd)/,/^(?:MITNFA)/,/^(?:NetCDF)/,/^(?:Naumen)/,/^(?:SMPPL)/,/^(?:Nunit)/,/^(?:FSFUL)/,/^(?:GL2PS)/,/^(?:SMLNJ)/,/^(?:Rdisc)/,/^(?:Noweb)/,/^(?:Nokia)/,/^(?:SISSL)/,/^(?:Qhull)/,/^(?:Intel)/,/^(?:Glide)/,/^(?:Xerox)/,/^(?:AMPAS)/,/^(?:WTFPL)/,/^(?:MS-PL)/,/^(?:XSkat)/,/^(?:MS-RL)/,/^(?:MirOS)/,/^(?:RSCPL)/,/^(?:TMate)/,/^(?:OGTSL)/,/^(?:FSFAP)/,/^(?:NCSA)/,/^(?:Zlib)/,/^(?:SCEA)/,/^(?:SNIA)/,/^(?:NGPL)/,/^(?:NOSL)/,/^(?:ADSL)/,/^(?:MTLL)/,/^(?:NLPL)/,/^(?:Ruby)/,/^(?:JSON)/,/^(?:Barr)/,/^(?:0BSD)/,/^(?:Xnet)/,/^(?:Cube)/,/^(?:curl)/,/^(?:DSDP)/,/^(?:Fair)/,/^(?:HPND)/,/^(?:TOSL)/,/^(?:IJG)/,/^(?:SWL)/,/^(?:Vim)/,/^(?:FTL)/,/^(?:ICU)/,/^(?:OML)/,/^(?:NRL)/,/^(?:DOC)/,/^(?:TCL)/,/^(?:W3C)/,/^(?:NTP)/,/^(?:IPA)/,/^(?:ISC)/,/^(?:X11)/,/^(?:AAL)/,/^(?:AML)/,/^(?:xpp)/,/^(?:Zed)/,/^(?:MIT)/,/^(?:Mup)/], +conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364],"inclusive":true}} +}); +return lexer; +})(); +parser.lexer = lexer; +function Parser () { + this.yy = {}; +} +Parser.prototype = parser;parser.Parser = Parser; +return new Parser; +})(); + + +if (true) { +exports.parser = spdxparse; +exports.Parser = spdxparse.Parser; +exports.parse = function () { return spdxparse.parse.apply(spdxparse, arguments); }; +exports.main = function commonjsMain(args) { + if (!args[1]) { + console.log('Usage: '+args[0]+' FILE'); + process.exit(1); + } + var source = __webpack_require__(23).readFileSync(__webpack_require__(16).normalize(args[1]), "utf8"); + return exports.parser.parse(source); +}; +if ( true && __webpack_require__.c[__webpack_require__.s] === module) { + exports.main(process.argv.slice(1)); +} +} + +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) + +/***/ }), +/* 79 */ +/***/ (function(module, exports, __webpack_require__) { + +var licenseIDs = __webpack_require__(80); + +function valid(string) { + return licenseIDs.indexOf(string) > -1; +} + +// Common transpositions of license identifier acronyms +var transpositions = [ + ['APGL', 'AGPL'], + ['Gpl', 'GPL'], + ['GLP', 'GPL'], + ['APL', 'Apache'], + ['ISD', 'ISC'], + ['GLP', 'GPL'], + ['IST', 'ISC'], + ['Claude', 'Clause'], + [' or later', '+'], + [' International', ''], + ['GNU', 'GPL'], + ['GUN', 'GPL'], + ['+', ''], + ['GNU GPL', 'GPL'], + ['GNU/GPL', 'GPL'], + ['GNU GLP', 'GPL'], + ['GNU General Public License', 'GPL'], + ['Gnu public license', 'GPL'], + ['GNU Public License', 'GPL'], + ['GNU GENERAL PUBLIC LICENSE', 'GPL'], + ['MTI', 'MIT'], + ['Mozilla Public License', 'MPL'], + ['WTH', 'WTF'], + ['-License', ''] +]; + +var TRANSPOSED = 0; +var CORRECT = 1; + +// Simple corrections to nearly valid identifiers. +var transforms = [ + // e.g. 'mit' + function(argument) { + return argument.toUpperCase(); + }, + // e.g. 'MIT ' + function(argument) { + return argument.trim(); + }, + // e.g. 'M.I.T.' + function(argument) { + return argument.replace(/\./g, ''); + }, + // e.g. 'Apache- 2.0' + function(argument) { + return argument.replace(/\s+/g, ''); + }, + // e.g. 'CC BY 4.0'' + function(argument) { + return argument.replace(/\s+/g, '-'); + }, + // e.g. 'LGPLv2.1' + function(argument) { + return argument.replace('v', '-'); + }, + // e.g. 'Apache 2.0' + function(argument) { + return argument.replace(/,?\s*(\d)/, '-$1'); + }, + // e.g. 'GPL 2' + function(argument) { + return argument.replace(/,?\s*(\d)/, '-$1.0'); + }, + // e.g. 'Apache Version 2.0' + function(argument) { + return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2'); + }, + // e.g. 'Apache Version 2' + function(argument) { + return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2.0'); + }, + // e.g. 'ZLIB' + function(argument) { + return argument[0].toUpperCase() + argument.slice(1); + }, + // e.g. 'MPL/2.0' + function(argument) { + return argument.replace('/', '-'); + }, + // e.g. 'Apache 2' + function(argument) { + return argument + .replace(/\s*V\s*(\d)/, '-$1') + .replace(/(\d)$/, '$1.0'); + }, + // e.g. 'GPL-2.0-' + function(argument) { + return argument.slice(0, argument.length - 1); + }, + // e.g. 'GPL2' + function(argument) { + return argument.replace(/(\d)$/, '-$1.0'); + }, + // e.g. 'BSD 3' + function(argument) { + return argument.replace(/(-| )?(\d)$/, '-$2-Clause'); + }, + // e.g. 'BSD clause 3' + function(argument) { + return argument.replace(/(-| )clause(-| )(\d)/, '-$3-Clause'); + }, + // e.g. 'BY-NC-4.0' + function(argument) { + return 'CC-' + argument; + }, + // e.g. 'BY-NC' + function(argument) { + return 'CC-' + argument + '-4.0'; + }, + // e.g. 'Attribution-NonCommercial' + function(argument) { + return argument + .replace('Attribution', 'BY') + .replace('NonCommercial', 'NC') + .replace('NoDerivatives', 'ND') + .replace(/ (\d)/, '-$1') + .replace(/ ?International/, ''); + }, + // e.g. 'Attribution-NonCommercial' + function(argument) { + return 'CC-' + + argument + .replace('Attribution', 'BY') + .replace('NonCommercial', 'NC') + .replace('NoDerivatives', 'ND') + .replace(/ (\d)/, '-$1') + .replace(/ ?International/, '') + + '-4.0'; + } +]; + +// If all else fails, guess that strings containing certain substrings +// meant to identify certain licenses. +var lastResorts = [ + ['UNLI', 'Unlicense'], + ['WTF', 'WTFPL'], + ['2 CLAUSE', 'BSD-2-Clause'], + ['2-CLAUSE', 'BSD-2-Clause'], + ['3 CLAUSE', 'BSD-3-Clause'], + ['3-CLAUSE', 'BSD-3-Clause'], + ['AFFERO', 'AGPL-3.0'], + ['AGPL', 'AGPL-3.0'], + ['APACHE', 'Apache-2.0'], + ['ARTISTIC', 'Artistic-2.0'], + ['Affero', 'AGPL-3.0'], + ['BEER', 'Beerware'], + ['BOOST', 'BSL-1.0'], + ['BSD', 'BSD-2-Clause'], + ['ECLIPSE', 'EPL-1.0'], + ['FUCK', 'WTFPL'], + ['GNU', 'GPL-3.0'], + ['LGPL', 'LGPL-3.0'], + ['GPL', 'GPL-3.0'], + ['MIT', 'MIT'], + ['MPL', 'MPL-2.0'], + ['X11', 'X11'], + ['ZLIB', 'Zlib'] +]; + +var SUBSTRING = 0; +var IDENTIFIER = 1; + +var validTransformation = function(identifier) { + for (var i = 0; i < transforms.length; i++) { + var transformed = transforms[i](identifier); + if (transformed !== identifier && valid(transformed)) { + return transformed; + } + } + return null; +}; + +var validLastResort = function(identifier) { + var upperCased = identifier.toUpperCase(); + for (var i = 0; i < lastResorts.length; i++) { + var lastResort = lastResorts[i]; + if (upperCased.indexOf(lastResort[SUBSTRING]) > -1) { + return lastResort[IDENTIFIER]; + } + } + return null; +}; + +var anyCorrection = function(identifier, check) { + for (var i = 0; i < transpositions.length; i++) { + var transposition = transpositions[i]; + var transposed = transposition[TRANSPOSED]; + if (identifier.indexOf(transposed) > -1) { + var corrected = identifier.replace( + transposed, + transposition[CORRECT] + ); + var checked = check(corrected); + if (checked !== null) { + return checked; + } + } + } + return null; +}; + +module.exports = function(identifier) { + identifier = identifier.replace(/\+$/, ''); + if (valid(identifier)) { + return identifier; + } + var transformed = validTransformation(identifier); + if (transformed !== null) { + return transformed; + } + transformed = anyCorrection(identifier, function(argument) { + if (valid(argument)) { + return argument; + } + return validTransformation(argument); + }); + if (transformed !== null) { + return transformed; + } + transformed = validLastResort(identifier); + if (transformed !== null) { + return transformed; + } + transformed = anyCorrection(identifier, validLastResort); + if (transformed !== null) { + return transformed; + } + return null; +}; + + +/***/ }), +/* 80 */ +/***/ (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\"]"); + +/***/ }), +/* 81 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var url = __webpack_require__(82) +var gitHosts = __webpack_require__(83) +var GitHost = module.exports = __webpack_require__(84) + +var protocolToRepresentationMap = { + 'git+ssh': 'sshurl', + 'git+https': 'https', + 'ssh': 'sshurl', + 'git': 'git' +} + +function protocolToRepresentation (protocol) { + if (protocol.substr(-1) === ':') protocol = protocol.slice(0, -1) + return protocolToRepresentationMap[protocol] || protocol +} + +var authProtocols = { + 'git:': true, + 'https:': true, + 'git+https:': true, + 'http:': true, + 'git+http:': true +} + +var cache = {} + +module.exports.fromUrl = function (giturl, opts) { + var key = giturl + JSON.stringify(opts || {}) + + if (!(key in cache)) { + cache[key] = fromUrl(giturl, opts) + } + + return cache[key] +} + +function fromUrl (giturl, opts) { + if (giturl == null || giturl === '') return + var url = fixupUnqualifiedGist( + isGitHubShorthand(giturl) ? 'github:' + giturl : giturl + ) + var parsed = parseGitUrl(url) + var shortcutMatch = url.match(new RegExp('^([^:]+):(?:(?:[^@:]+(?:[^@]+)?@)?([^/]*))[/](.+?)(?:[.]git)?($|#)')) + var matches = Object.keys(gitHosts).map(function (gitHostName) { + try { + var gitHostInfo = gitHosts[gitHostName] + var auth = null + if (parsed.auth && authProtocols[parsed.protocol]) { + auth = decodeURIComponent(parsed.auth) + } + var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null + var user = null + var project = null + var defaultRepresentation = null + if (shortcutMatch && shortcutMatch[1] === gitHostName) { + user = shortcutMatch[2] && decodeURIComponent(shortcutMatch[2]) + project = decodeURIComponent(shortcutMatch[3]) + defaultRepresentation = 'shortcut' + } else { + if (parsed.host !== gitHostInfo.domain) return + if (!gitHostInfo.protocols_re.test(parsed.protocol)) return + if (!parsed.path) return + var pathmatch = gitHostInfo.pathmatch + var matched = parsed.path.match(pathmatch) + if (!matched) return + if (matched[1] != null) user = decodeURIComponent(matched[1].replace(/^:/, '')) + if (matched[2] != null) project = decodeURIComponent(matched[2]) + defaultRepresentation = protocolToRepresentation(parsed.protocol) + } + return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts) + } catch (ex) { + if (!(ex instanceof URIError)) throw ex + } + }).filter(function (gitHostInfo) { return gitHostInfo }) + if (matches.length !== 1) return + return matches[0] +} + +function isGitHubShorthand (arg) { + // Note: This does not fully test the git ref format. + // See https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html + // + // The only way to do this properly would be to shell out to + // git-check-ref-format, and as this is a fast sync function, + // we don't want to do that. Just let git fail if it turns + // out that the commit-ish is invalid. + // GH usernames cannot start with . or - + return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg) +} + +function fixupUnqualifiedGist (giturl) { + // necessary for round-tripping gists + var parsed = url.parse(giturl) + if (parsed.protocol === 'gist:' && parsed.host && !parsed.path) { + return parsed.protocol + '/' + parsed.host + } else { + return giturl + } +} + +function parseGitUrl (giturl) { + if (typeof giturl !== 'string') giturl = '' + giturl + var matched = giturl.match(/^([^@]+)@([^:/]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/) + if (!matched) return url.parse(giturl) + return { + protocol: 'git+ssh:', + slashes: true, + auth: matched[1], + host: matched[2], + port: null, + hostname: matched[2], + hash: matched[4], + search: null, + query: null, + pathname: '/' + matched[3], + path: '/' + matched[3], + href: 'git+ssh://' + matched[1] + '@' + matched[2] + + '/' + matched[3] + (matched[4] || '') + } +} + + +/***/ }), +/* 82 */ +/***/ (function(module, exports) { + +module.exports = require("url"); + +/***/ }), +/* 83 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var gitHosts = module.exports = { + github: { + // First two are insecure and generally shouldn't be used any more, but + // they are still supported. + 'protocols': [ 'git', 'http', 'git+ssh', 'git+https', 'ssh', 'https' ], + 'domain': 'github.com', + 'treepath': 'tree', + 'filetemplate': 'https://{auth@}raw.githubusercontent.com/{user}/{project}/{committish}/{path}', + 'bugstemplate': 'https://{domain}/{user}/{project}/issues', + 'gittemplate': 'git://{auth@}{domain}/{user}/{project}.git{#committish}', + 'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz' + }, + bitbucket: { + 'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ], + 'domain': 'bitbucket.org', + 'treepath': 'src', + 'tarballtemplate': 'https://{domain}/{user}/{project}/get/{committish}.tar.gz' + }, + gitlab: { + 'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ], + 'domain': 'gitlab.com', + 'treepath': 'tree', + 'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#README', + 'bugstemplate': 'https://{domain}/{user}/{project}/issues', + 'tarballtemplate': 'https://{domain}/{user}/{project}/repository/archive.tar.gz?ref={committish}' + }, + gist: { + 'protocols': [ 'git', 'git+ssh', 'git+https', 'ssh', 'https' ], + 'domain': 'gist.github.com', + 'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]+)(?:[.]git)?$/, + 'filetemplate': 'https://gist.githubusercontent.com/{user}/{project}/raw{/committish}/{path}', + 'bugstemplate': 'https://{domain}/{project}', + 'gittemplate': 'git://{domain}/{project}.git{#committish}', + 'sshtemplate': 'git@{domain}:/{project}.git{#committish}', + 'sshurltemplate': 'git+ssh://git@{domain}/{project}.git{#committish}', + 'browsetemplate': 'https://{domain}/{project}{/committish}', + 'docstemplate': 'https://{domain}/{project}{/committish}', + 'httpstemplate': 'git+https://{domain}/{project}.git{#committish}', + 'shortcuttemplate': '{type}:{project}{#committish}', + 'pathtemplate': '{project}{#committish}', + 'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz' + } +} + +var gitHostDefaults = { + 'sshtemplate': 'git@{domain}:{user}/{project}.git{#committish}', + 'sshurltemplate': 'git+ssh://git@{domain}/{user}/{project}.git{#committish}', + 'browsetemplate': 'https://{domain}/{user}/{project}{/tree/committish}', + 'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#readme', + 'httpstemplate': 'git+https://{auth@}{domain}/{user}/{project}.git{#committish}', + 'filetemplate': 'https://{domain}/{user}/{project}/raw/{committish}/{path}', + 'shortcuttemplate': '{type}:{user}/{project}{#committish}', + 'pathtemplate': '{user}/{project}{#committish}', + 'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/ +} + +Object.keys(gitHosts).forEach(function (name) { + Object.keys(gitHostDefaults).forEach(function (key) { + if (gitHosts[name][key]) return + gitHosts[name][key] = gitHostDefaults[key] + }) + gitHosts[name].protocols_re = RegExp('^(' + + gitHosts[name].protocols.map(function (protocol) { + return protocol.replace(/([\\+*{}()[\]$^|])/g, '\\$1') + }).join('|') + '):$') +}) + + +/***/ }), +/* 84 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var gitHosts = __webpack_require__(83) +var extend = Object.assign || __webpack_require__(29)._extend + +var GitHost = module.exports = function (type, user, auth, project, committish, defaultRepresentation, opts) { + var gitHostInfo = this + gitHostInfo.type = type + Object.keys(gitHosts[type]).forEach(function (key) { + gitHostInfo[key] = gitHosts[type][key] + }) + gitHostInfo.user = user + gitHostInfo.auth = auth + gitHostInfo.project = project + gitHostInfo.committish = committish + gitHostInfo.default = defaultRepresentation + gitHostInfo.opts = opts || {} +} +GitHost.prototype = {} + +GitHost.prototype.hash = function () { + return this.committish ? '#' + this.committish : '' +} + +GitHost.prototype._fill = function (template, opts) { + if (!template) return + var vars = extend({}, opts) + opts = extend(extend({}, this.opts), opts) + var self = this + Object.keys(this).forEach(function (key) { + if (self[key] != null && vars[key] == null) vars[key] = self[key] + }) + var rawAuth = vars.auth + var rawComittish = vars.committish + Object.keys(vars).forEach(function (key) { + vars[key] = encodeURIComponent(vars[key]) + }) + vars['auth@'] = rawAuth ? rawAuth + '@' : '' + if (opts.noCommittish) { + vars['#committish'] = '' + vars['/tree/committish'] = '' + vars['/comittish'] = '' + vars.comittish = '' + } else { + vars['#committish'] = rawComittish ? '#' + rawComittish : '' + vars['/tree/committish'] = vars.committish + ? '/' + vars.treepath + '/' + vars.committish + : '' + vars['/committish'] = vars.committish ? '/' + vars.committish : '' + vars.committish = vars.committish || 'master' + } + var res = template + Object.keys(vars).forEach(function (key) { + res = res.replace(new RegExp('[{]' + key + '[}]', 'g'), vars[key]) + }) + if (opts.noGitPlus) { + return res.replace(/^git[+]/, '') + } else { + return res + } +} + +GitHost.prototype.ssh = function (opts) { + return this._fill(this.sshtemplate, opts) +} + +GitHost.prototype.sshurl = function (opts) { + return this._fill(this.sshurltemplate, opts) +} + +GitHost.prototype.browse = function (opts) { + return this._fill(this.browsetemplate, opts) +} + +GitHost.prototype.docs = function (opts) { + return this._fill(this.docstemplate, opts) +} + +GitHost.prototype.bugs = function (opts) { + return this._fill(this.bugstemplate, opts) +} + +GitHost.prototype.https = function (opts) { + return this._fill(this.httpstemplate, opts) +} + +GitHost.prototype.git = function (opts) { + return this._fill(this.gittemplate, opts) +} + +GitHost.prototype.shortcut = function (opts) { + return this._fill(this.shortcuttemplate, opts) +} + +GitHost.prototype.path = function (opts) { + return this._fill(this.pathtemplate, opts) +} + +GitHost.prototype.tarball = function (opts) { + return this._fill(this.tarballtemplate, opts) +} + +GitHost.prototype.file = function (P, opts) { + return this._fill(this.filetemplate, extend({ + path: P.replace(/^[/]+/g, '') + }, opts)) +} + +GitHost.prototype.getDefaultRepresentation = function () { + return this.default +} + +GitHost.prototype.toString = function (opts) { + return (this[this.default] || this.sshurl).call(this, opts) +} + + +/***/ }), +/* 85 */ +/***/ (function(module, exports, __webpack_require__) { + +var core = __webpack_require__(86); +var async = __webpack_require__(88); +async.core = core; +async.isCore = function isCore(x) { return core[x]; }; +async.sync = __webpack_require__(93); + +exports = async; +module.exports = async; + + +/***/ }), +/* 86 */ +/***/ (function(module, exports, __webpack_require__) { + +var current = (process.versions && process.versions.node && process.versions.node.split('.')) || []; + +function specifierIncluded(specifier) { + var parts = specifier.split(' '); + var op = parts.length > 1 ? parts[0] : '='; + var versionParts = (parts.length > 1 ? parts[1] : parts[0]).split('.'); + + for (var i = 0; i < 3; ++i) { + var cur = Number(current[i] || 0); + var ver = Number(versionParts[i] || 0); + if (cur === ver) { + continue; // eslint-disable-line no-restricted-syntax, no-continue + } + if (op === '<') { + return cur < ver; + } else if (op === '>=') { + return cur >= ver; + } else { + return false; + } + } + return op === '>='; +} + +function matchesRange(range) { + var specifiers = range.split(/ ?&& ?/); + if (specifiers.length === 0) { return false; } + for (var i = 0; i < specifiers.length; ++i) { + if (!specifierIncluded(specifiers[i])) { return false; } + } + return true; +} + +function versionIncluded(specifierValue) { + if (typeof specifierValue === 'boolean') { return specifierValue; } + if (specifierValue && typeof specifierValue === 'object') { + for (var i = 0; i < specifierValue.length; ++i) { + if (matchesRange(specifierValue[i])) { return true; } + } + return false; + } + return matchesRange(specifierValue); +} + +var data = __webpack_require__(87); + +var core = {}; +for (var mod in data) { // eslint-disable-line no-restricted-syntax + if (Object.prototype.hasOwnProperty.call(data, mod)) { + core[mod] = versionIncluded(data[mod]); + } +} +module.exports = core; + + +/***/ }), +/* 87 */ +/***/ (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,\"_debugger\":\"< 8\",\"dgram\":true,\"dns\":true,\"domain\":true,\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":\">= 10 && < 10.1\",\"_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\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0\",\"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\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8\":\">= 1\",\"vm\":true,\"worker_threads\":\">= 11.7\",\"zlib\":true}"); + +/***/ }), +/* 88 */ +/***/ (function(module, exports, __webpack_require__) { + +var core = __webpack_require__(86); +var fs = __webpack_require__(23); +var path = __webpack_require__(16); +var caller = __webpack_require__(89); +var nodeModulesPaths = __webpack_require__(90); +var normalizeOptions = __webpack_require__(92); + +var defaultIsFile = function isFile(file, cb) { + fs.stat(file, function (err, stat) { + if (!err) { + return cb(null, stat.isFile() || stat.isFIFO()); + } + if (err.code === 'ENOENT' || err.code === 'ENOTDIR') return cb(null, false); + return cb(err); + }); +}; + +module.exports = function resolve(x, options, callback) { + var cb = callback; + var opts = options; + if (typeof options === 'function') { + cb = opts; + opts = {}; + } + if (typeof x !== 'string') { + var err = new TypeError('Path must be a string.'); + return process.nextTick(function () { + cb(err); + }); + } + + opts = normalizeOptions(x, opts); + + var isFile = opts.isFile || defaultIsFile; + var readFile = opts.readFile || fs.readFile; + + var extensions = opts.extensions || ['.js']; + var basedir = opts.basedir || path.dirname(caller()); + var parent = opts.filename || basedir; + + opts.paths = opts.paths || []; + + // ensure that `basedir` is an absolute path at this point, resolving against the process' current working directory + var absoluteStart = path.resolve(basedir); + + if (opts.preserveSymlinks === false) { + fs.realpath(absoluteStart, function (realPathErr, realStart) { + if (realPathErr && realPathErr.code !== 'ENOENT') cb(err); + else init(realPathErr ? absoluteStart : realStart); + }); + } else { + init(absoluteStart); + } + + var res; + function init(basedir) { + if ((/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/).test(x)) { + res = path.resolve(basedir, x); + if (x === '..' || x.slice(-1) === '/') res += '/'; + if ((/\/$/).test(x) && res === basedir) { + loadAsDirectory(res, opts.package, onfile); + } else loadAsFile(res, opts.package, onfile); + } else loadNodeModules(x, basedir, function (err, n, pkg) { + if (err) cb(err); + else if (n) cb(null, n, pkg); + else if (core[x]) return cb(null, x); + else { + var moduleError = new Error("Cannot find module '" + x + "' from '" + parent + "'"); + moduleError.code = 'MODULE_NOT_FOUND'; + cb(moduleError); + } + }); + } + + function onfile(err, m, pkg) { + if (err) cb(err); + else if (m) cb(null, m, pkg); + else loadAsDirectory(res, function (err, d, pkg) { + if (err) cb(err); + else if (d) cb(null, d, pkg); + else { + var moduleError = new Error("Cannot find module '" + x + "' from '" + parent + "'"); + moduleError.code = 'MODULE_NOT_FOUND'; + cb(moduleError); + } + }); + } + + function loadAsFile(x, thePackage, callback) { + var loadAsFilePackage = thePackage; + var cb = callback; + if (typeof loadAsFilePackage === 'function') { + cb = loadAsFilePackage; + loadAsFilePackage = undefined; + } + + var exts = [''].concat(extensions); + load(exts, x, loadAsFilePackage); + + function load(exts, x, loadPackage) { + if (exts.length === 0) return cb(null, undefined, loadPackage); + var file = x + exts[0]; + + var pkg = loadPackage; + if (pkg) onpkg(null, pkg); + else loadpkg(path.dirname(file), onpkg); + + function onpkg(err, pkg_, dir) { + pkg = pkg_; + if (err) return cb(err); + if (dir && pkg && opts.pathFilter) { + var rfile = path.relative(dir, file); + var rel = rfile.slice(0, rfile.length - exts[0].length); + var r = opts.pathFilter(pkg, x, rel); + if (r) return load( + [''].concat(extensions.slice()), + path.resolve(dir, r), + pkg + ); + } + isFile(file, onex); + } + function onex(err, ex) { + if (err) return cb(err); + if (ex) return cb(null, file, pkg); + load(exts.slice(1), x, pkg); + } + } + } + + function loadpkg(dir, cb) { + if (dir === '' || dir === '/') return cb(null); + if (process.platform === 'win32' && (/^\w:[/\\]*$/).test(dir)) { + return cb(null); + } + if ((/[/\\]node_modules[/\\]*$/).test(dir)) return cb(null); + + var pkgfile = path.join(dir, 'package.json'); + isFile(pkgfile, function (err, ex) { + // on err, ex is false + if (!ex) return loadpkg(path.dirname(dir), cb); + + readFile(pkgfile, function (err, body) { + if (err) cb(err); + try { var pkg = JSON.parse(body); } catch (jsonErr) {} + + if (pkg && opts.packageFilter) { + pkg = opts.packageFilter(pkg, pkgfile); + } + cb(null, pkg, dir); + }); + }); + } + + function loadAsDirectory(x, loadAsDirectoryPackage, callback) { + var cb = callback; + var fpkg = loadAsDirectoryPackage; + if (typeof fpkg === 'function') { + cb = fpkg; + fpkg = opts.package; + } + + var pkgfile = path.join(x, 'package.json'); + isFile(pkgfile, function (err, ex) { + if (err) return cb(err); + if (!ex) return loadAsFile(path.join(x, 'index'), fpkg, cb); + + readFile(pkgfile, function (err, body) { + if (err) return cb(err); + try { + var pkg = JSON.parse(body); + } catch (jsonErr) {} + + if (opts.packageFilter) { + pkg = opts.packageFilter(pkg, pkgfile); + } + + if (pkg.main) { + if (typeof pkg.main !== 'string') { + var mainError = new TypeError('package “' + pkg.name + '” `main` must be a string'); + mainError.code = 'INVALID_PACKAGE_MAIN'; + return cb(mainError); + } + if (pkg.main === '.' || pkg.main === './') { + pkg.main = 'index'; + } + loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) { + if (err) return cb(err); + if (m) return cb(null, m, pkg); + if (!pkg) return loadAsFile(path.join(x, 'index'), pkg, cb); + + var dir = path.resolve(x, pkg.main); + loadAsDirectory(dir, pkg, function (err, n, pkg) { + if (err) return cb(err); + if (n) return cb(null, n, pkg); + loadAsFile(path.join(x, 'index'), pkg, cb); + }); + }); + return; + } + + loadAsFile(path.join(x, '/index'), pkg, cb); + }); + }); + } + + function processDirs(cb, dirs) { + if (dirs.length === 0) return cb(null, undefined); + var dir = dirs[0]; + + var file = path.join(dir, x); + loadAsFile(file, opts.package, onfile); + + function onfile(err, m, pkg) { + if (err) return cb(err); + if (m) return cb(null, m, pkg); + loadAsDirectory(path.join(dir, x), opts.package, ondir); + } + + function ondir(err, n, pkg) { + if (err) return cb(err); + if (n) return cb(null, n, pkg); + processDirs(cb, dirs.slice(1)); + } + } + function loadNodeModules(x, start, cb) { + processDirs(cb, nodeModulesPaths(start, opts, x)); + } +}; + + +/***/ }), +/* 89 */ +/***/ (function(module, exports) { + +module.exports = function () { + // see https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi + var origPrepareStackTrace = Error.prepareStackTrace; + Error.prepareStackTrace = function (_, stack) { return stack; }; + var stack = (new Error()).stack; + Error.prepareStackTrace = origPrepareStackTrace; + return stack[2].getFileName(); +}; + + +/***/ }), +/* 90 */ +/***/ (function(module, exports, __webpack_require__) { + +var path = __webpack_require__(16); +var parse = path.parse || __webpack_require__(91); + +var getNodeModulesDirs = function getNodeModulesDirs(absoluteStart, modules) { + var prefix = '/'; + if ((/^([A-Za-z]:)/).test(absoluteStart)) { + prefix = ''; + } else if ((/^\\\\/).test(absoluteStart)) { + prefix = '\\\\'; + } + + var paths = [absoluteStart]; + var parsed = parse(absoluteStart); + while (parsed.dir !== paths[paths.length - 1]) { + paths.push(parsed.dir); + parsed = parse(parsed.dir); + } + + return paths.reduce(function (dirs, aPath) { + return dirs.concat(modules.map(function (moduleDir) { + return path.join(prefix, aPath, moduleDir); + })); + }, []); +}; + +module.exports = function nodeModulesPaths(start, opts, request) { + var modules = opts && opts.moduleDirectory + ? [].concat(opts.moduleDirectory) + : ['node_modules']; + + if (opts && typeof opts.paths === 'function') { + return opts.paths( + request, + start, + function () { return getNodeModulesDirs(start, modules); }, + opts + ); + } + + var dirs = getNodeModulesDirs(start, modules); + return opts && opts.paths ? dirs.concat(opts.paths) : dirs; +}; + + +/***/ }), +/* 91 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var isWindows = process.platform === 'win32'; + +// Regex to split a windows path into three parts: [*, device, slash, +// tail] windows-only +var splitDeviceRe = + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + +// Regex to split the tail part of the above into [*, dir, basename, ext] +var splitTailRe = + /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; + +var win32 = {}; + +// Function to split a filename into [root, dir, basename, ext] +function win32SplitPath(filename) { + // Separate device+slash from tail + var result = splitDeviceRe.exec(filename), + device = (result[1] || '') + (result[2] || ''), + tail = result[3] || ''; + // Split the tail into dir, basename and extension + var result2 = splitTailRe.exec(tail), + dir = result2[1], + basename = result2[2], + ext = result2[3]; + return [device, dir, basename, ext]; +} + +win32.parse = function(pathString) { + if (typeof pathString !== 'string') { + throw new TypeError( + "Parameter 'pathString' must be a string, not " + typeof pathString + ); + } + var allParts = win32SplitPath(pathString); + if (!allParts || allParts.length !== 4) { + throw new TypeError("Invalid path '" + pathString + "'"); + } + return { + root: allParts[0], + dir: allParts[0] + allParts[1].slice(0, -1), + base: allParts[2], + ext: allParts[3], + name: allParts[2].slice(0, allParts[2].length - allParts[3].length) + }; +}; + + + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var posix = {}; + + +function posixSplitPath(filename) { + return splitPathRe.exec(filename).slice(1); +} + + +posix.parse = function(pathString) { + if (typeof pathString !== 'string') { + throw new TypeError( + "Parameter 'pathString' must be a string, not " + typeof pathString + ); + } + var allParts = posixSplitPath(pathString); + if (!allParts || allParts.length !== 4) { + throw new TypeError("Invalid path '" + pathString + "'"); + } + allParts[1] = allParts[1] || ''; + allParts[2] = allParts[2] || ''; + allParts[3] = allParts[3] || ''; + + return { + root: allParts[0], + dir: allParts[0] + allParts[1].slice(0, -1), + base: allParts[2], + ext: allParts[3], + name: allParts[2].slice(0, allParts[2].length - allParts[3].length) + }; +}; + + +if (isWindows) + module.exports = win32.parse; +else /* posix */ + module.exports = posix.parse; + +module.exports.posix = posix.parse; +module.exports.win32 = win32.parse; + + +/***/ }), +/* 92 */ +/***/ (function(module, exports) { + +module.exports = function (x, opts) { + /** + * This file is purposefully a passthrough. It's expected that third-party + * environments will override it at runtime in order to inject special logic + * into `resolve` (by manipulating the options). One such example is the PnP + * code path in Yarn. + */ + + return opts || {}; +}; + + +/***/ }), +/* 93 */ +/***/ (function(module, exports, __webpack_require__) { + +var core = __webpack_require__(86); +var fs = __webpack_require__(23); +var path = __webpack_require__(16); +var caller = __webpack_require__(89); +var nodeModulesPaths = __webpack_require__(90); +var normalizeOptions = __webpack_require__(92); + +var defaultIsFile = function isFile(file) { + try { + var stat = fs.statSync(file); + } catch (e) { + if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) return false; + throw e; + } + return stat.isFile() || stat.isFIFO(); +}; + +module.exports = function (x, options) { + if (typeof x !== 'string') { + throw new TypeError('Path must be a string.'); + } + var opts = normalizeOptions(x, options); + + var isFile = opts.isFile || defaultIsFile; + var readFileSync = opts.readFileSync || fs.readFileSync; + + var extensions = opts.extensions || ['.js']; + var basedir = opts.basedir || path.dirname(caller()); + var parent = opts.filename || basedir; + + opts.paths = opts.paths || []; + + // ensure that `basedir` is an absolute path at this point, resolving against the process' current working directory + var absoluteStart = path.resolve(basedir); + + if (opts.preserveSymlinks === false) { + try { + absoluteStart = fs.realpathSync(absoluteStart); + } catch (realPathErr) { + if (realPathErr.code !== 'ENOENT') { + throw realPathErr; + } + } + } + + if ((/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/).test(x)) { + var res = path.resolve(absoluteStart, x); + if (x === '..' || x.slice(-1) === '/') res += '/'; + var m = loadAsFileSync(res) || loadAsDirectorySync(res); + if (m) return m; + } else { + var n = loadNodeModulesSync(x, absoluteStart); + if (n) return n; + } + + if (core[x]) return x; + + var err = new Error("Cannot find module '" + x + "' from '" + parent + "'"); + err.code = 'MODULE_NOT_FOUND'; + throw err; + + function loadAsFileSync(x) { + var pkg = loadpkg(path.dirname(x)); + + if (pkg && pkg.dir && pkg.pkg && opts.pathFilter) { + var rfile = path.relative(pkg.dir, x); + var r = opts.pathFilter(pkg.pkg, x, rfile); + if (r) { + x = path.resolve(pkg.dir, r); // eslint-disable-line no-param-reassign + } + } + + if (isFile(x)) { + return x; + } + + for (var i = 0; i < extensions.length; i++) { + var file = x + extensions[i]; + if (isFile(file)) { + return file; + } + } + } + + function loadpkg(dir) { + if (dir === '' || dir === '/') return; + if (process.platform === 'win32' && (/^\w:[/\\]*$/).test(dir)) { + return; + } + if ((/[/\\]node_modules[/\\]*$/).test(dir)) return; + + var pkgfile = path.join(dir, 'package.json'); + + if (!isFile(pkgfile)) { + return loadpkg(path.dirname(dir)); + } + + var body = readFileSync(pkgfile); + + try { + var pkg = JSON.parse(body); + } catch (jsonErr) {} + + if (pkg && opts.packageFilter) { + pkg = opts.packageFilter(pkg, dir); + } + + return { pkg: pkg, dir: dir }; + } + + function loadAsDirectorySync(x) { + var pkgfile = path.join(x, '/package.json'); + if (isFile(pkgfile)) { + try { + var body = readFileSync(pkgfile, 'UTF8'); + var pkg = JSON.parse(body); + } catch (e) {} + + if (opts.packageFilter) { + pkg = opts.packageFilter(pkg, x); + } + + if (pkg.main) { + if (typeof pkg.main !== 'string') { + var mainError = new TypeError('package “' + pkg.name + '” `main` must be a string'); + mainError.code = 'INVALID_PACKAGE_MAIN'; + throw mainError; + } + if (pkg.main === '.' || pkg.main === './') { + pkg.main = 'index'; + } + try { + var m = loadAsFileSync(path.resolve(x, pkg.main)); + if (m) return m; + var n = loadAsDirectorySync(path.resolve(x, pkg.main)); + if (n) return n; + } catch (e) {} + } + } + + return loadAsFileSync(path.join(x, '/index')); + } + + function loadNodeModulesSync(x, start) { + var dirs = nodeModulesPaths(start, opts, x); + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i]; + var m = loadAsFileSync(path.join(dir, '/', x)); + if (m) return m; + var n = loadAsDirectorySync(path.join(dir, '/', x)); + if (n) return n; + } + } +}; + + +/***/ }), +/* 94 */ +/***/ (function(module, exports) { + +module.exports = extractDescription + +// Extracts description from contents of a readme file in markdown format +function extractDescription (d) { + if (!d) return; + if (d === "ERROR: No README data found!") return; + // the first block of text before the first heading + // that isn't the first line heading + d = d.trim().split('\n') + for (var s = 0; d[s] && d[s].trim().match(/^(#|$)/); s ++); + var l = d.length + for (var e = s + 1; e < l && d[e].trim(); e ++); + return d.slice(s, e).join(' ').trim() +} + + +/***/ }), +/* 95 */ +/***/ (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\"}}"); + +/***/ }), +/* 96 */ +/***/ (function(module, exports, __webpack_require__) { + +var util = __webpack_require__(29) +var messages = __webpack_require__(97) + +module.exports = function() { + var args = Array.prototype.slice.call(arguments, 0) + var warningName = args.shift() + if (warningName == "typo") { + return makeTypoWarning.apply(null,args) + } + else { + var msgTemplate = messages[warningName] ? messages[warningName] : warningName + ": '%s'" + args.unshift(msgTemplate) + return util.format.apply(null, args) + } +} + +function makeTypoWarning (providedName, probableName, field) { + if (field) { + providedName = field + "['" + providedName + "']" + probableName = field + "['" + probableName + "']" + } + return util.format(messages.typo, providedName, probableName) +} + + +/***/ }), +/* 97 */ +/***/ (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.\"}"); + +/***/ }), +/* 98 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const path = __webpack_require__(16); +const writeJsonFile = __webpack_require__(99); +const sortKeys = __webpack_require__(113); + +const dependencyKeys = new Set([ + 'dependencies', + 'devDependencies', + 'optionalDependencies', + 'peerDependencies' +]); + +function normalize(packageJson) { + const result = {}; + + for (const key of Object.keys(packageJson)) { + if (!dependencyKeys.has(key)) { + result[key] = packageJson[key]; + } else if (Object.keys(packageJson[key]).length !== 0) { + result[key] = sortKeys(packageJson[key]); + } + } + + return result; +} + +module.exports = async (filePath, data, options) => { + if (typeof filePath !== 'string') { + options = data; + data = filePath; + filePath = '.'; + } + + options = { + normalize: true, + ...options, + detectIndent: true + }; + + filePath = path.basename(filePath) === 'package.json' ? filePath : path.join(filePath, 'package.json'); + + data = options.normalize ? normalize(data) : data; + + return writeJsonFile(filePath, data, options); +}; + +module.exports.sync = (filePath, data, options) => { + if (typeof filePath !== 'string') { + options = data; + data = filePath; + filePath = '.'; + } + + options = { + normalize: true, + ...options, + detectIndent: true + }; + + filePath = path.basename(filePath) === 'package.json' ? filePath : path.join(filePath, 'package.json'); + + data = options.normalize ? normalize(data) : data; + + writeJsonFile.sync(filePath, data, options); +}; + + +/***/ }), +/* 99 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const path = __webpack_require__(16); +const fs = __webpack_require__(100); +const writeFileAtomic = __webpack_require__(104); +const sortKeys = __webpack_require__(113); +const makeDir = __webpack_require__(115); +const pify = __webpack_require__(116); +const detectIndent = __webpack_require__(118); + +const init = (fn, filePath, data, options) => { + if (!filePath) { + throw new TypeError('Expected a filepath'); + } + + if (data === undefined) { + throw new TypeError('Expected data to stringify'); + } + + options = Object.assign({ + indent: '\t', + sortKeys: false + }, options); + + if (options.sortKeys) { + data = sortKeys(data, { + deep: true, + compare: typeof options.sortKeys === 'function' ? options.sortKeys : undefined + }); + } + + return fn(filePath, data, options); +}; + +const readFile = filePath => pify(fs.readFile)(filePath, 'utf8').catch(() => {}); + +const main = (filePath, data, options) => { + return (options.detectIndent ? readFile(filePath) : Promise.resolve()) + .then(string => { + const indent = string ? detectIndent(string).indent : options.indent; + const json = JSON.stringify(data, options.replacer, indent); + + return pify(writeFileAtomic)(filePath, `${json}\n`, {mode: options.mode}); + }); +}; + +const mainSync = (filePath, data, options) => { + let {indent} = options; + + if (options.detectIndent) { + try { + const file = fs.readFileSync(filePath, 'utf8'); + indent = detectIndent(file).indent; + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } + } + + const json = JSON.stringify(data, options.replacer, indent); + + return writeFileAtomic.sync(filePath, `${json}\n`, {mode: options.mode}); +}; + +const writeJsonFile = (filePath, data, options) => { + return makeDir(path.dirname(filePath), {fs}) + .then(() => init(main, filePath, data, options)); +}; + +module.exports = writeJsonFile; +// TODO: Remove this for the next major release +module.exports.default = writeJsonFile; +module.exports.sync = (filePath, data, options) => { + makeDir.sync(path.dirname(filePath), {fs}); + init(mainSync, filePath, data, options); +}; + + +/***/ }), +/* 100 */ +/***/ (function(module, exports, __webpack_require__) { + +var fs = __webpack_require__(23) +var polyfills = __webpack_require__(101) +var legacy = __webpack_require__(102) +var clone = __webpack_require__(103) + +var queue = [] + +var util = __webpack_require__(29) + +function noop () {} + +var debug = noop +if (util.debuglog) + debug = util.debuglog('gfs4') +else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) + debug = function() { + var m = util.format.apply(util, arguments) + m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ') + console.error(m) + } + +if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { + process.on('exit', function() { + debug(queue) + __webpack_require__(30).equal(queue.length, 0) + }) +} + +module.exports = patch(clone(fs)) +if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) { + module.exports = patch(fs) + fs.__patched = true; +} + +// Always patch fs.close/closeSync, because we want to +// retry() whenever a close happens *anywhere* in the program. +// This is essential when multiple graceful-fs instances are +// in play at the same time. +module.exports.close = (function (fs$close) { return function (fd, cb) { + return fs$close.call(fs, fd, function (err) { + if (!err) + retry() + + if (typeof cb === 'function') + cb.apply(this, arguments) + }) +}})(fs.close) + +module.exports.closeSync = (function (fs$closeSync) { return function (fd) { + // Note that graceful-fs also retries when fs.closeSync() fails. + // Looks like a bug to me, although it's probably a harmless one. + var rval = fs$closeSync.apply(fs, arguments) + retry() + return rval +}})(fs.closeSync) + +// Only patch fs once, otherwise we'll run into a memory leak if +// graceful-fs is loaded multiple times, such as in test environments that +// reset the loaded modules between tests. +// We look for the string `graceful-fs` from the comment above. This +// way we are not adding any extra properties and it will detect if older +// versions of graceful-fs are installed. +if (!/\bgraceful-fs\b/.test(fs.closeSync.toString())) { + fs.closeSync = module.exports.closeSync; + fs.close = module.exports.close; +} + +function patch (fs) { + // Everything that references the open() function needs to be in here + polyfills(fs) + fs.gracefulify = patch + fs.FileReadStream = ReadStream; // Legacy name. + fs.FileWriteStream = WriteStream; // Legacy name. + fs.createReadStream = createReadStream + fs.createWriteStream = createWriteStream + var fs$readFile = fs.readFile + fs.readFile = readFile + function readFile (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$readFile(path, options, cb) + + function go$readFile (path, options, cb) { + return fs$readFile(path, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readFile, [path, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$writeFile = fs.writeFile + fs.writeFile = writeFile + function writeFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$writeFile(path, data, options, cb) + + function go$writeFile (path, data, options, cb) { + return fs$writeFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$writeFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$appendFile = fs.appendFile + if (fs$appendFile) + fs.appendFile = appendFile + function appendFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$appendFile(path, data, options, cb) + + function go$appendFile (path, data, options, cb) { + return fs$appendFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$appendFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$readdir = fs.readdir + fs.readdir = readdir + function readdir (path, options, cb) { + var args = [path] + if (typeof options !== 'function') { + args.push(options) + } else { + cb = options + } + args.push(go$readdir$cb) + + return go$readdir(args) + + function go$readdir$cb (err, files) { + if (files && files.sort) + files.sort() + + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readdir, [args]]) + + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + } + } + + function go$readdir (args) { + return fs$readdir.apply(fs, args) + } + + if (process.version.substr(0, 4) === 'v0.8') { + var legStreams = legacy(fs) + ReadStream = legStreams.ReadStream + WriteStream = legStreams.WriteStream + } + + var fs$ReadStream = fs.ReadStream + if (fs$ReadStream) { + ReadStream.prototype = Object.create(fs$ReadStream.prototype) + ReadStream.prototype.open = ReadStream$open + } + + var fs$WriteStream = fs.WriteStream + if (fs$WriteStream) { + WriteStream.prototype = Object.create(fs$WriteStream.prototype) + WriteStream.prototype.open = WriteStream$open + } + + fs.ReadStream = ReadStream + fs.WriteStream = WriteStream + + function ReadStream (path, options) { + if (this instanceof ReadStream) + return fs$ReadStream.apply(this, arguments), this + else + return ReadStream.apply(Object.create(ReadStream.prototype), arguments) + } + + function ReadStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + if (that.autoClose) + that.destroy() + + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + that.read() + } + }) + } + + function WriteStream (path, options) { + if (this instanceof WriteStream) + return fs$WriteStream.apply(this, arguments), this + else + return WriteStream.apply(Object.create(WriteStream.prototype), arguments) + } + + function WriteStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + that.destroy() + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + } + }) + } + + function createReadStream (path, options) { + return new ReadStream(path, options) + } + + function createWriteStream (path, options) { + return new WriteStream(path, options) + } + + var fs$open = fs.open + fs.open = open + function open (path, flags, mode, cb) { + if (typeof mode === 'function') + cb = mode, mode = null + + return go$open(path, flags, mode, cb) + + function go$open (path, flags, mode, cb) { + return fs$open(path, flags, mode, function (err, fd) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$open, [path, flags, mode, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + return fs +} + +function enqueue (elem) { + debug('ENQUEUE', elem[0].name, elem[1]) + queue.push(elem) +} + +function retry () { + var elem = queue.shift() + if (elem) { + debug('RETRY', elem[0].name, elem[1]) + elem[0].apply(null, elem[1]) + } +} + + +/***/ }), +/* 101 */ +/***/ (function(module, exports, __webpack_require__) { + +var constants = __webpack_require__(26) + +var origCwd = process.cwd +var cwd = null + +var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform + +process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process) + return cwd +} +try { + process.cwd() +} catch (er) {} + +var chdir = process.chdir +process.chdir = function(d) { + cwd = null + chdir.call(process, d) +} + +module.exports = patch + +function patch (fs) { + // (re-)implement some things that are known busted or missing. + + // lchmod, broken prior to 0.6.2 + // back-port the fix here. + if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + patchLchmod(fs) + } + + // lutimes implementation, or no-op + if (!fs.lutimes) { + patchLutimes(fs) + } + + // https://github.com/isaacs/node-graceful-fs/issues/4 + // Chown should not fail on einval or eperm if non-root. + // It should not fail on enosys ever, as this just indicates + // that a fs doesn't support the intended operation. + + fs.chown = chownFix(fs.chown) + fs.fchown = chownFix(fs.fchown) + fs.lchown = chownFix(fs.lchown) + + fs.chmod = chmodFix(fs.chmod) + fs.fchmod = chmodFix(fs.fchmod) + fs.lchmod = chmodFix(fs.lchmod) + + fs.chownSync = chownFixSync(fs.chownSync) + fs.fchownSync = chownFixSync(fs.fchownSync) + fs.lchownSync = chownFixSync(fs.lchownSync) + + fs.chmodSync = chmodFixSync(fs.chmodSync) + fs.fchmodSync = chmodFixSync(fs.fchmodSync) + fs.lchmodSync = chmodFixSync(fs.lchmodSync) + + fs.stat = statFix(fs.stat) + fs.fstat = statFix(fs.fstat) + fs.lstat = statFix(fs.lstat) + + fs.statSync = statFixSync(fs.statSync) + fs.fstatSync = statFixSync(fs.fstatSync) + fs.lstatSync = statFixSync(fs.lstatSync) + + // if lchmod/lchown do not exist, then make them no-ops + if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + if (cb) process.nextTick(cb) + } + fs.lchmodSync = function () {} + } + if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + if (cb) process.nextTick(cb) + } + fs.lchownSync = function () {} + } + + // on Windows, A/V software can lock the directory, causing this + // to fail with an EACCES or EPERM if the directory contains newly + // created files. Try again on failure, for up to 60 seconds. + + // Set the timeout this long because some Windows Anti-Virus, such as Parity + // bit9, may lock files for up to a minute, causing npm package install + // failures. Also, take care to yield the scheduler. Windows scheduling gives + // CPU to a busy looping process, which can cause the program causing the lock + // contention to be starved of CPU by node, so the contention doesn't resolve. + if (platform === "win32") { + fs.rename = (function (fs$rename) { return function (from, to, cb) { + var start = Date.now() + var backoff = 0; + fs$rename(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 60000) { + setTimeout(function() { + fs.stat(to, function (stater, st) { + if (stater && stater.code === "ENOENT") + fs$rename(from, to, CB); + else + cb(er) + }) + }, backoff) + if (backoff < 100) + backoff += 10; + return; + } + if (cb) cb(er) + }) + }})(fs.rename) + } + + // if read() returns EAGAIN, then just try it again. + fs.read = (function (fs$read) { return function (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + }})(fs.read) + + fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return fs$readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } + }})(fs.readSync) + + function patchLchmod (fs) { + fs.lchmod = function (path, mode, callback) { + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + if (callback) callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + if (callback) callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var threw = true + var ret + try { + ret = fs.fchmodSync(fd, mode) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + } + + function patchLutimes (fs) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + if (er) { + if (cb) cb(er) + return + } + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + if (cb) cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + var ret + var threw = true + try { + ret = fs.futimesSync(fd, at, mt) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + + } else { + fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) } + fs.lutimesSync = function () {} + } + } + + function chmodFix (orig) { + if (!orig) return orig + return function (target, mode, cb) { + return orig.call(fs, target, mode, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chmodFixSync (orig) { + if (!orig) return orig + return function (target, mode) { + try { + return orig.call(fs, target, mode) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + + function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + + function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } + + + function statFix (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, cb) { + return orig.call(fs, target, function (er, stats) { + if (!stats) return cb.apply(this, arguments) + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + if (cb) cb.apply(this, arguments) + }) + } + } + + function statFixSync (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target) { + var stats = orig.call(fs, target) + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + return stats; + } + } + + // ENOSYS means that the fs doesn't support the op. Just ignore + // that, because it doesn't matter. + // + // if there's no getuid, or if getuid() is something other + // than 0, and the error is EINVAL or EPERM, then just ignore + // it. + // + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // + // When running as root, or if other types of errors are + // encountered, then it's strict. + function chownErOk (er) { + if (!er) + return true + + if (er.code === "ENOSYS") + return true + + var nonroot = !process.getuid || process.getuid() !== 0 + if (nonroot) { + if (er.code === "EINVAL" || er.code === "EPERM") + return true + } + + return false + } +} + + +/***/ }), +/* 102 */ +/***/ (function(module, exports, __webpack_require__) { + +var Stream = __webpack_require__(28).Stream + +module.exports = legacy + +function legacy (fs) { + return { + ReadStream: ReadStream, + WriteStream: WriteStream + } + + function ReadStream (path, options) { + if (!(this instanceof ReadStream)) return new ReadStream(path, options); + + Stream.call(this); + + var self = this; + + this.path = path; + this.fd = null; + this.readable = true; + this.paused = false; + + this.flags = 'r'; + this.mode = 438; /*=0666*/ + this.bufferSize = 64 * 1024; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.encoding) this.setEncoding(this.encoding); + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.end === undefined) { + this.end = Infinity; + } else if ('number' !== typeof this.end) { + throw TypeError('end must be a Number'); + } + + if (this.start > this.end) { + throw new Error('start must be <= end'); + } + + this.pos = this.start; + } + + if (this.fd !== null) { + process.nextTick(function() { + self._read(); + }); + return; + } + + fs.open(this.path, this.flags, this.mode, function (err, fd) { + if (err) { + self.emit('error', err); + self.readable = false; + return; + } + + self.fd = fd; + self.emit('open', fd); + self._read(); + }) + } + + function WriteStream (path, options) { + if (!(this instanceof WriteStream)) return new WriteStream(path, options); + + Stream.call(this); + + this.path = path; + this.fd = null; + this.writable = true; + + this.flags = 'w'; + this.encoding = 'binary'; + this.mode = 438; /*=0666*/ + this.bytesWritten = 0; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.start < 0) { + throw new Error('start must be >= zero'); + } + + this.pos = this.start; + } + + this.busy = false; + this._queue = []; + + if (this.fd === null) { + this._open = fs.open; + this._queue.push([this._open, this.path, this.flags, this.mode, undefined]); + this.flush(); + } + } +} + + +/***/ }), +/* 103 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = clone + +function clone (obj) { + if (obj === null || typeof obj !== 'object') + return obj + + if (obj instanceof Object) + var copy = { __proto__: obj.__proto__ } + else + var copy = Object.create(null) + + Object.getOwnPropertyNames(obj).forEach(function (key) { + Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key)) + }) + + return copy +} + + +/***/ }), +/* 104 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = writeFile +module.exports.sync = writeFileSync +module.exports._getTmpname = getTmpname // for testing +module.exports._cleanupOnExit = cleanupOnExit + +var fs = __webpack_require__(105) +var MurmurHash3 = __webpack_require__(109) +var onExit = __webpack_require__(110) +var path = __webpack_require__(16) +var activeFiles = {} + +// if we run inside of a worker_thread, `process.pid` is not unique +/* istanbul ignore next */ +var threadId = (function getId () { + try { + var workerThreads = __webpack_require__(112) + + /// if we are in main thread, this is set to `0` + return workerThreads.threadId + } catch (e) { + // worker_threads are not available, fallback to 0 + return 0 + } +})() + +var invocations = 0 +function getTmpname (filename) { + return filename + '.' + + MurmurHash3(__filename) + .hash(String(process.pid)) + .hash(String(threadId)) + .hash(String(++invocations)) + .result() +} + +function cleanupOnExit (tmpfile) { + return function () { + try { + fs.unlinkSync(typeof tmpfile === 'function' ? tmpfile() : tmpfile) + } catch (_) {} + } +} + +function writeFile (filename, data, options, callback) { + if (options) { + if (options instanceof Function) { + callback = options + options = {} + } else if (typeof options === 'string') { + options = { encoding: options } + } + } else { + options = {} + } + + var Promise = options.Promise || global.Promise + var truename + var fd + var tmpfile + /* istanbul ignore next -- The closure only gets called when onExit triggers */ + var removeOnExitHandler = onExit(cleanupOnExit(() => tmpfile)) + var absoluteName = path.resolve(filename) + + new Promise(function serializeSameFile (resolve) { + // make a queue if it doesn't already exist + if (!activeFiles[absoluteName]) activeFiles[absoluteName] = [] + + activeFiles[absoluteName].push(resolve) // add this job to the queue + if (activeFiles[absoluteName].length === 1) resolve() // kick off the first one + }).then(function getRealPath () { + return new Promise(function (resolve) { + fs.realpath(filename, function (_, realname) { + truename = realname || filename + tmpfile = getTmpname(truename) + resolve() + }) + }) + }).then(function stat () { + return new Promise(function stat (resolve) { + if (options.mode && options.chown) resolve() + else { + // Either mode or chown is not explicitly set + // Default behavior is to copy it from original file + fs.stat(truename, function (err, stats) { + if (err || !stats) resolve() + else { + options = Object.assign({}, options) + + if (options.mode == null) { + options.mode = stats.mode + } + if (options.chown == null && process.getuid) { + options.chown = { uid: stats.uid, gid: stats.gid } + } + resolve() + } + }) + } + }) + }).then(function thenWriteFile () { + return new Promise(function (resolve, reject) { + fs.open(tmpfile, 'w', options.mode, function (err, _fd) { + fd = _fd + if (err) reject(err) + else resolve() + }) + }) + }).then(function write () { + return new Promise(function (resolve, reject) { + if (Buffer.isBuffer(data)) { + fs.write(fd, data, 0, data.length, 0, function (err) { + if (err) reject(err) + else resolve() + }) + } else if (data != null) { + fs.write(fd, String(data), 0, String(options.encoding || 'utf8'), function (err) { + if (err) reject(err) + else resolve() + }) + } else resolve() + }) + }).then(function syncAndClose () { + return new Promise(function (resolve, reject) { + if (options.fsync !== false) { + fs.fsync(fd, function (err) { + if (err) fs.close(fd, () => reject(err)) + else fs.close(fd, resolve) + }) + } else { + fs.close(fd, resolve) + } + }) + }).then(function chown () { + fd = null + if (options.chown) { + return new Promise(function (resolve, reject) { + fs.chown(tmpfile, options.chown.uid, options.chown.gid, function (err) { + if (err) reject(err) + else resolve() + }) + }) + } + }).then(function chmod () { + if (options.mode) { + return new Promise(function (resolve, reject) { + fs.chmod(tmpfile, options.mode, function (err) { + if (err) reject(err) + else resolve() + }) + }) + } + }).then(function rename () { + return new Promise(function (resolve, reject) { + fs.rename(tmpfile, truename, function (err) { + if (err) reject(err) + else resolve() + }) + }) + }).then(function success () { + removeOnExitHandler() + callback() + }, function fail (err) { + return new Promise(resolve => { + return fd ? fs.close(fd, resolve) : resolve() + }).then(() => { + removeOnExitHandler() + fs.unlink(tmpfile, function () { + callback(err) + }) + }) + }).then(function checkQueue () { + activeFiles[absoluteName].shift() // remove the element added by serializeSameFile + if (activeFiles[absoluteName].length > 0) { + activeFiles[absoluteName][0]() // start next job if one is pending + } else delete activeFiles[absoluteName] + }) +} + +function writeFileSync (filename, data, options) { + if (typeof options === 'string') options = { encoding: options } + else if (!options) options = {} + try { + filename = fs.realpathSync(filename) + } catch (ex) { + // it's ok, it'll happen on a not yet existing file + } + var tmpfile = getTmpname(filename) + + if (!options.mode || !options.chown) { + // Either mode or chown is not explicitly set + // Default behavior is to copy it from original file + try { + var stats = fs.statSync(filename) + options = Object.assign({}, options) + if (!options.mode) { + options.mode = stats.mode + } + if (!options.chown && process.getuid) { + options.chown = { uid: stats.uid, gid: stats.gid } + } + } catch (ex) { + // ignore stat errors + } + } + + var fd + var cleanup = cleanupOnExit(tmpfile) + var removeOnExitHandler = onExit(cleanup) + + try { + fd = fs.openSync(tmpfile, 'w', options.mode) + if (Buffer.isBuffer(data)) { + fs.writeSync(fd, data, 0, data.length, 0) + } else if (data != null) { + fs.writeSync(fd, String(data), 0, String(options.encoding || 'utf8')) + } + if (options.fsync !== false) { + fs.fsyncSync(fd) + } + fs.closeSync(fd) + if (options.chown) fs.chownSync(tmpfile, options.chown.uid, options.chown.gid) + if (options.mode) fs.chmodSync(tmpfile, options.mode) + fs.renameSync(tmpfile, filename) + removeOnExitHandler() + } catch (err) { + if (fd) { + try { + fs.closeSync(fd) + } catch (ex) { + // ignore close errors at this stage, error may have closed fd already. + } + } + removeOnExitHandler() + cleanup() + throw err + } +} + + +/***/ }), +/* 105 */ +/***/ (function(module, exports, __webpack_require__) { + +var fs = __webpack_require__(23) +var polyfills = __webpack_require__(106) +var legacy = __webpack_require__(108) +var queue = [] + +var util = __webpack_require__(29) + +function noop () {} + +var debug = noop +if (util.debuglog) + debug = util.debuglog('gfs4') +else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) + debug = function() { + var m = util.format.apply(util, arguments) + m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ') + console.error(m) + } + +if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { + process.on('exit', function() { + debug(queue) + __webpack_require__(30).equal(queue.length, 0) + }) +} + +module.exports = patch(__webpack_require__(107)) +if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) { + module.exports = patch(fs) +} + +// Always patch fs.close/closeSync, because we want to +// retry() whenever a close happens *anywhere* in the program. +// This is essential when multiple graceful-fs instances are +// in play at the same time. +module.exports.close = +fs.close = (function (fs$close) { return function (fd, cb) { + return fs$close.call(fs, fd, function (err) { + if (!err) + retry() + + if (typeof cb === 'function') + cb.apply(this, arguments) + }) +}})(fs.close) + +module.exports.closeSync = +fs.closeSync = (function (fs$closeSync) { return function (fd) { + // Note that graceful-fs also retries when fs.closeSync() fails. + // Looks like a bug to me, although it's probably a harmless one. + var rval = fs$closeSync.apply(fs, arguments) + retry() + return rval +}})(fs.closeSync) + +function patch (fs) { + // Everything that references the open() function needs to be in here + polyfills(fs) + fs.gracefulify = patch + fs.FileReadStream = ReadStream; // Legacy name. + fs.FileWriteStream = WriteStream; // Legacy name. + fs.createReadStream = createReadStream + fs.createWriteStream = createWriteStream + var fs$readFile = fs.readFile + fs.readFile = readFile + function readFile (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$readFile(path, options, cb) + + function go$readFile (path, options, cb) { + return fs$readFile(path, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readFile, [path, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$writeFile = fs.writeFile + fs.writeFile = writeFile + function writeFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$writeFile(path, data, options, cb) + + function go$writeFile (path, data, options, cb) { + return fs$writeFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$writeFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$appendFile = fs.appendFile + if (fs$appendFile) + fs.appendFile = appendFile + function appendFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$appendFile(path, data, options, cb) + + function go$appendFile (path, data, options, cb) { + return fs$appendFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$appendFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$readdir = fs.readdir + fs.readdir = readdir + function readdir (path, options, cb) { + var args = [path] + if (typeof options !== 'function') { + args.push(options) + } else { + cb = options + } + args.push(go$readdir$cb) + + return go$readdir(args) + + function go$readdir$cb (err, files) { + if (files && files.sort) + files.sort() + + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readdir, [args]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + } + } + + function go$readdir (args) { + return fs$readdir.apply(fs, args) + } + + if (process.version.substr(0, 4) === 'v0.8') { + var legStreams = legacy(fs) + ReadStream = legStreams.ReadStream + WriteStream = legStreams.WriteStream + } + + var fs$ReadStream = fs.ReadStream + ReadStream.prototype = Object.create(fs$ReadStream.prototype) + ReadStream.prototype.open = ReadStream$open + + var fs$WriteStream = fs.WriteStream + WriteStream.prototype = Object.create(fs$WriteStream.prototype) + WriteStream.prototype.open = WriteStream$open + + fs.ReadStream = ReadStream + fs.WriteStream = WriteStream + + function ReadStream (path, options) { + if (this instanceof ReadStream) + return fs$ReadStream.apply(this, arguments), this + else + return ReadStream.apply(Object.create(ReadStream.prototype), arguments) + } + + function ReadStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + if (that.autoClose) + that.destroy() + + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + that.read() + } + }) + } + + function WriteStream (path, options) { + if (this instanceof WriteStream) + return fs$WriteStream.apply(this, arguments), this + else + return WriteStream.apply(Object.create(WriteStream.prototype), arguments) + } + + function WriteStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + that.destroy() + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + } + }) + } + + function createReadStream (path, options) { + return new ReadStream(path, options) + } + + function createWriteStream (path, options) { + return new WriteStream(path, options) + } + + var fs$open = fs.open + fs.open = open + function open (path, flags, mode, cb) { + if (typeof mode === 'function') + cb = mode, mode = null + + return go$open(path, flags, mode, cb) + + function go$open (path, flags, mode, cb) { + return fs$open(path, flags, mode, function (err, fd) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$open, [path, flags, mode, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + return fs +} + +function enqueue (elem) { + debug('ENQUEUE', elem[0].name, elem[1]) + queue.push(elem) +} + +function retry () { + var elem = queue.shift() + if (elem) { + debug('RETRY', elem[0].name, elem[1]) + elem[0].apply(null, elem[1]) + } +} + + +/***/ }), +/* 106 */ +/***/ (function(module, exports, __webpack_require__) { + +var fs = __webpack_require__(107) +var constants = __webpack_require__(26) + +var origCwd = process.cwd +var cwd = null + +var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform + +process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process) + return cwd +} +try { + process.cwd() +} catch (er) {} + +var chdir = process.chdir +process.chdir = function(d) { + cwd = null + chdir.call(process, d) +} + +module.exports = patch + +function patch (fs) { + // (re-)implement some things that are known busted or missing. + + // lchmod, broken prior to 0.6.2 + // back-port the fix here. + if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + patchLchmod(fs) + } + + // lutimes implementation, or no-op + if (!fs.lutimes) { + patchLutimes(fs) + } + + // https://github.com/isaacs/node-graceful-fs/issues/4 + // Chown should not fail on einval or eperm if non-root. + // It should not fail on enosys ever, as this just indicates + // that a fs doesn't support the intended operation. + + fs.chown = chownFix(fs.chown) + fs.fchown = chownFix(fs.fchown) + fs.lchown = chownFix(fs.lchown) + + fs.chmod = chmodFix(fs.chmod) + fs.fchmod = chmodFix(fs.fchmod) + fs.lchmod = chmodFix(fs.lchmod) + + fs.chownSync = chownFixSync(fs.chownSync) + fs.fchownSync = chownFixSync(fs.fchownSync) + fs.lchownSync = chownFixSync(fs.lchownSync) + + fs.chmodSync = chmodFixSync(fs.chmodSync) + fs.fchmodSync = chmodFixSync(fs.fchmodSync) + fs.lchmodSync = chmodFixSync(fs.lchmodSync) + + fs.stat = statFix(fs.stat) + fs.fstat = statFix(fs.fstat) + fs.lstat = statFix(fs.lstat) + + fs.statSync = statFixSync(fs.statSync) + fs.fstatSync = statFixSync(fs.fstatSync) + fs.lstatSync = statFixSync(fs.lstatSync) + + // if lchmod/lchown do not exist, then make them no-ops + if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + if (cb) process.nextTick(cb) + } + fs.lchmodSync = function () {} + } + if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + if (cb) process.nextTick(cb) + } + fs.lchownSync = function () {} + } + + // on Windows, A/V software can lock the directory, causing this + // to fail with an EACCES or EPERM if the directory contains newly + // created files. Try again on failure, for up to 60 seconds. + + // Set the timeout this long because some Windows Anti-Virus, such as Parity + // bit9, may lock files for up to a minute, causing npm package install + // failures. Also, take care to yield the scheduler. Windows scheduling gives + // CPU to a busy looping process, which can cause the program causing the lock + // contention to be starved of CPU by node, so the contention doesn't resolve. + if (platform === "win32") { + fs.rename = (function (fs$rename) { return function (from, to, cb) { + var start = Date.now() + var backoff = 0; + fs$rename(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 60000) { + setTimeout(function() { + fs.stat(to, function (stater, st) { + if (stater && stater.code === "ENOENT") + fs$rename(from, to, CB); + else + cb(er) + }) + }, backoff) + if (backoff < 100) + backoff += 10; + return; + } + if (cb) cb(er) + }) + }})(fs.rename) + } + + // if read() returns EAGAIN, then just try it again. + fs.read = (function (fs$read) { return function (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + }})(fs.read) + + fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return fs$readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } + }})(fs.readSync) +} + +function patchLchmod (fs) { + fs.lchmod = function (path, mode, callback) { + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + if (callback) callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + if (callback) callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var threw = true + var ret + try { + ret = fs.fchmodSync(fd, mode) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } +} + +function patchLutimes (fs) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + if (er) { + if (cb) cb(er) + return + } + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + if (cb) cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + var ret + var threw = true + try { + ret = fs.futimesSync(fd, at, mt) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + + } else { + fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) } + fs.lutimesSync = function () {} + } +} + +function chmodFix (orig) { + if (!orig) return orig + return function (target, mode, cb) { + return orig.call(fs, target, mode, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } +} + +function chmodFixSync (orig) { + if (!orig) return orig + return function (target, mode) { + try { + return orig.call(fs, target, mode) + } catch (er) { + if (!chownErOk(er)) throw er + } + } +} + + +function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } +} + +function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } +} + + +function statFix (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, cb) { + return orig.call(fs, target, function (er, stats) { + if (!stats) return cb.apply(this, arguments) + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + if (cb) cb.apply(this, arguments) + }) + } +} + +function statFixSync (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target) { + var stats = orig.call(fs, target) + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + return stats; + } +} + +// ENOSYS means that the fs doesn't support the op. Just ignore +// that, because it doesn't matter. +// +// if there's no getuid, or if getuid() is something other +// than 0, and the error is EINVAL or EPERM, then just ignore +// it. +// +// This specific case is a silent failure in cp, install, tar, +// and most other unix tools that manage permissions. +// +// When running as root, or if other types of errors are +// encountered, then it's strict. +function chownErOk (er) { + if (!er) + return true + + if (er.code === "ENOSYS") + return true + + var nonroot = !process.getuid || process.getuid() !== 0 + if (nonroot) { + if (er.code === "EINVAL" || er.code === "EPERM") + return true + } + + return false +} + + +/***/ }), +/* 107 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var fs = __webpack_require__(23) + +module.exports = clone(fs) + +function clone (obj) { + if (obj === null || typeof obj !== 'object') + return obj + + if (obj instanceof Object) + var copy = { __proto__: obj.__proto__ } + else + var copy = Object.create(null) + + Object.getOwnPropertyNames(obj).forEach(function (key) { + Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key)) + }) + + return copy +} + + +/***/ }), +/* 108 */ +/***/ (function(module, exports, __webpack_require__) { + +var Stream = __webpack_require__(28).Stream + +module.exports = legacy + +function legacy (fs) { + return { + ReadStream: ReadStream, + WriteStream: WriteStream + } + + function ReadStream (path, options) { + if (!(this instanceof ReadStream)) return new ReadStream(path, options); + + Stream.call(this); + + var self = this; + + this.path = path; + this.fd = null; + this.readable = true; + this.paused = false; + + this.flags = 'r'; + this.mode = 438; /*=0666*/ + this.bufferSize = 64 * 1024; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.encoding) this.setEncoding(this.encoding); + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.end === undefined) { + this.end = Infinity; + } else if ('number' !== typeof this.end) { + throw TypeError('end must be a Number'); + } + + if (this.start > this.end) { + throw new Error('start must be <= end'); + } + + this.pos = this.start; + } + + if (this.fd !== null) { + process.nextTick(function() { + self._read(); + }); + return; + } + + fs.open(this.path, this.flags, this.mode, function (err, fd) { + if (err) { + self.emit('error', err); + self.readable = false; + return; + } + + self.fd = fd; + self.emit('open', fd); + self._read(); + }) + } + + function WriteStream (path, options) { + if (!(this instanceof WriteStream)) return new WriteStream(path, options); + + Stream.call(this); + + this.path = path; + this.fd = null; + this.writable = true; + + this.flags = 'w'; + this.encoding = 'binary'; + this.mode = 438; /*=0666*/ + this.bytesWritten = 0; + + options = options || {}; + + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } + + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.start < 0) { + throw new Error('start must be >= zero'); + } + + this.pos = this.start; + } + + this.busy = false; + this._queue = []; + + if (this.fd === null) { + this._open = fs.open; + this._queue.push([this._open, this.path, this.flags, this.mode, undefined]); + this.flush(); + } + } +} + + +/***/ }), +/* 109 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * @preserve + * JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013) + * + * @author Jens Taylor + * @see http://github.com/homebrewing/brauhaus-diff + * @author Gary Court + * @see http://github.com/garycourt/murmurhash-js + * @author Austin Appleby + * @see http://sites.google.com/site/murmurhash/ + */ +(function(){ + var cache; + + // Call this function without `new` to use the cached object (good for + // single-threaded environments), or with `new` to create a new object. + // + // @param {string} key A UTF-16 or ASCII string + // @param {number} seed An optional positive integer + // @return {object} A MurmurHash3 object for incremental hashing + function MurmurHash3(key, seed) { + var m = this instanceof MurmurHash3 ? this : cache; + m.reset(seed) + if (typeof key === 'string' && key.length > 0) { + m.hash(key); + } + + if (m !== this) { + return m; + } + }; + + // Incrementally add a string to this hash + // + // @param {string} key A UTF-16 or ASCII string + // @return {object} this + MurmurHash3.prototype.hash = function(key) { + var h1, k1, i, top, len; + + len = key.length; + this.len += len; + + k1 = this.k1; + i = 0; + switch (this.rem) { + case 0: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) : 0; + case 1: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 8 : 0; + case 2: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 16 : 0; + case 3: + k1 ^= len > i ? (key.charCodeAt(i) & 0xff) << 24 : 0; + k1 ^= len > i ? (key.charCodeAt(i++) & 0xff00) >> 8 : 0; + } + + this.rem = (len + this.rem) & 3; // & 3 is same as % 4 + len -= this.rem; + if (len > 0) { + h1 = this.h1; + while (1) { + k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); + h1 = (h1 * 5 + 0xe6546b64) & 0xffffffff; + + if (i >= len) { + break; + } + + k1 = ((key.charCodeAt(i++) & 0xffff)) ^ + ((key.charCodeAt(i++) & 0xffff) << 8) ^ + ((key.charCodeAt(i++) & 0xffff) << 16); + top = key.charCodeAt(i++); + k1 ^= ((top & 0xff) << 24) ^ + ((top & 0xff00) >> 8); + } + + k1 = 0; + switch (this.rem) { + case 3: k1 ^= (key.charCodeAt(i + 2) & 0xffff) << 16; + case 2: k1 ^= (key.charCodeAt(i + 1) & 0xffff) << 8; + case 1: k1 ^= (key.charCodeAt(i) & 0xffff); + } + + this.h1 = h1; + } + + this.k1 = k1; + return this; + }; + + // Get the result of this hash + // + // @return {number} The 32-bit hash + MurmurHash3.prototype.result = function() { + var k1, h1; + + k1 = this.k1; + h1 = this.h1; + + if (k1 > 0) { + k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; + h1 ^= k1; + } + + h1 ^= this.len; + + h1 ^= h1 >>> 16; + h1 = (h1 * 0xca6b + (h1 & 0xffff) * 0x85eb0000) & 0xffffffff; + h1 ^= h1 >>> 13; + h1 = (h1 * 0xae35 + (h1 & 0xffff) * 0xc2b20000) & 0xffffffff; + h1 ^= h1 >>> 16; + + return h1 >>> 0; + }; + + // Reset the hash object for reuse + // + // @param {number} seed An optional positive integer + MurmurHash3.prototype.reset = function(seed) { + this.h1 = typeof seed === 'number' ? seed : 0; + this.rem = this.k1 = this.len = 0; + return this; + }; + + // A cached object to use. This can be safely used if you're in a single- + // threaded environment, otherwise you need to create new hashes to use. + cache = new MurmurHash3(); + + if (true) { + module.exports = MurmurHash3; + } else {} +}()); + + +/***/ }), +/* 110 */ +/***/ (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__(30) +var signals = __webpack_require__(111) + +var EE = __webpack_require__(46) +/* istanbul ignore if */ +if (typeof EE !== 'function') { + EE = EE.EventEmitter +} + +var emitter +if (process.__signal_exit_emitter__) { + emitter = process.__signal_exit_emitter__ +} else { + emitter = process.__signal_exit_emitter__ = new EE() + emitter.count = 0 + emitter.emitted = {} +} + +// Because this emitter is a global, we have to check to see if a +// previous version of this library failed to enable infinite listeners. +// I know what you're about to say. But literally everything about +// signal-exit is a compromise with evil. Get used to it. +if (!emitter.infinite) { + emitter.setMaxListeners(Infinity) + emitter.infinite = true +} + +module.exports = function (cb, opts) { + assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler') + + if (loaded === false) { + load() + } + + var ev = 'exit' + if (opts && opts.alwaysLast) { + ev = 'afterexit' + } + + var remove = function () { + emitter.removeListener(ev, cb) + if (emitter.listeners('exit').length === 0 && + emitter.listeners('afterexit').length === 0) { + unload() + } + } + emitter.on(ev, cb) + + return remove +} + +module.exports.unload = unload +function unload () { + if (!loaded) { + return + } + loaded = false + + signals.forEach(function (sig) { + try { + process.removeListener(sig, sigListeners[sig]) + } catch (er) {} + }) + process.emit = originalProcessEmit + process.reallyExit = originalProcessReallyExit + emitter.count -= 1 +} + +function emit (event, code, signal) { + if (emitter.emitted[event]) { + return + } + emitter.emitted[event] = true + emitter.emit(event, code, signal) +} + +// { : , ... } +var sigListeners = {} +signals.forEach(function (sig) { + sigListeners[sig] = function listener () { + // If there are no other listeners, an exit is coming! + // Simplest way: remove us and then re-send the signal. + // We know that this will kill the process, so we can + // safely emit now. + var listeners = process.listeners(sig) + if (listeners.length === emitter.count) { + unload() + emit('exit', null, sig) + /* istanbul ignore next */ + emit('afterexit', null, sig) + /* istanbul ignore next */ + process.kill(process.pid, sig) + } + } +}) + +module.exports.signals = function () { + return signals +} + +module.exports.load = load + +var loaded = false + +function load () { + if (loaded) { + return + } + loaded = true + + // This is the number of onSignalExit's that are in play. + // It's important so that we can count the correct number of + // listeners on signals, and don't wait for the other one to + // handle it instead of us. + emitter.count += 1 + + signals = signals.filter(function (sig) { + try { + process.on(sig, sigListeners[sig]) + return true + } catch (er) { + return false + } + }) + + process.emit = processEmit + process.reallyExit = processReallyExit +} + +var originalProcessReallyExit = process.reallyExit +function processReallyExit (code) { + process.exitCode = code || 0 + emit('exit', process.exitCode, null) + /* istanbul ignore next */ + emit('afterexit', process.exitCode, null) + /* istanbul ignore next */ + originalProcessReallyExit.call(process, process.exitCode) +} + +var originalProcessEmit = process.emit +function processEmit (ev, arg) { + if (ev === 'exit') { + if (arg !== undefined) { + process.exitCode = arg + } + var ret = originalProcessEmit.apply(this, arguments) + emit('exit', process.exitCode, null) + /* istanbul ignore next */ + emit('afterexit', process.exitCode, null) + return ret + } else { + return originalProcessEmit.apply(this, arguments) + } +} + + +/***/ }), +/* 111 */ +/***/ (function(module, exports) { + +// This is not the set of all possible signals. +// +// It IS, however, the set of all signals that trigger +// an exit on either Linux or BSD systems. Linux is a +// superset of the signal names supported on BSD, and +// the unknown signals just fail to register, so we can +// catch that easily enough. +// +// Don't bother with SIGKILL. It's uncatchable, which +// means that we can't fire any callbacks anyway. +// +// If a user does happen to register a handler on a non- +// fatal signal like SIGWINCH or something, and then +// exit, it'll end up firing `process.emit('exit')`, so +// the handler will be fired anyway. +// +// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised +// artificially, inherently leave the process in a +// state from which it is not safe to try and enter JS +// listeners. +module.exports = [ + 'SIGABRT', + 'SIGALRM', + 'SIGHUP', + 'SIGINT', + 'SIGTERM' +] + +if (process.platform !== 'win32') { + module.exports.push( + 'SIGVTALRM', + 'SIGXCPU', + 'SIGXFSZ', + 'SIGUSR2', + 'SIGTRAP', + 'SIGSYS', + 'SIGQUIT', + 'SIGIOT' + // should detect profiler and enable/disable accordingly. + // see #21 + // 'SIGPROF' + ) +} + +if (process.platform === 'linux') { + module.exports.push( + 'SIGIO', + 'SIGPOLL', + 'SIGPWR', + 'SIGSTKFLT', + 'SIGUNUSED' + ) +} + + +/***/ }), +/* 112 */ +/***/ (function(module, exports) { + +module.exports = require(undefined); + +/***/ }), +/* 113 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const isPlainObj = __webpack_require__(114); + +module.exports = (obj, opts) => { + if (!isPlainObj(obj)) { + throw new TypeError('Expected a plain object'); + } + + opts = opts || {}; + + // DEPRECATED + if (typeof opts === 'function') { + throw new TypeError('Specify the compare function as an option instead'); + } + + const deep = opts.deep; + const seenInput = []; + const seenOutput = []; + + const sortKeys = x => { + const seenIndex = seenInput.indexOf(x); + + if (seenIndex !== -1) { + return seenOutput[seenIndex]; + } + + const ret = {}; + const keys = Object.keys(x).sort(opts.compare); + + seenInput.push(x); + seenOutput.push(ret); + + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const val = x[key]; + + if (deep && Array.isArray(val)) { + const retArr = []; + + for (let j = 0; j < val.length; j++) { + retArr[j] = isPlainObj(val[j]) ? sortKeys(val[j]) : val[j]; + } + + ret[key] = retArr; + continue; + } + + ret[key] = deep && isPlainObj(val) ? sortKeys(val) : val; + } + + return ret; + }; + + return sortKeys(obj); +}; + + +/***/ }), +/* 114 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var toString = Object.prototype.toString; + +module.exports = function (x) { + var prototype; + return toString.call(x) === '[object Object]' && (prototype = Object.getPrototypeOf(x), prototype === null || prototype === Object.getPrototypeOf({})); +}; + + +/***/ }), +/* 115 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const fs = __webpack_require__(23); +const path = __webpack_require__(16); +const pify = __webpack_require__(116); +const semver = __webpack_require__(117); + +const defaults = { + mode: 0o777 & (~process.umask()), + fs +}; + +const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); + +// https://github.com/nodejs/node/issues/8987 +// https://github.com/libuv/libuv/pull/1088 +const checkPath = pth => { + if (process.platform === 'win32') { + const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, '')); + + if (pathHasInvalidWinCharacters) { + const error = new Error(`Path contains invalid characters: ${pth}`); + error.code = 'EINVAL'; + throw error; + } + } +}; + +const permissionError = pth => { + // This replicates the exception of `fs.mkdir` with native the + // `recusive` option when run on an invalid drive under Windows. + const error = new Error(`operation not permitted, mkdir '${pth}'`); + error.code = 'EPERM'; + error.errno = -4048; + error.path = pth; + error.syscall = 'mkdir'; + return error; +}; + +const makeDir = (input, options) => Promise.resolve().then(() => { + checkPath(input); + options = Object.assign({}, defaults, options); + + // TODO: Use util.promisify when targeting Node.js 8 + const mkdir = pify(options.fs.mkdir); + const stat = pify(options.fs.stat); + + if (useNativeRecursiveOption && options.fs.mkdir === fs.mkdir) { + const pth = path.resolve(input); + + return mkdir(pth, { + mode: options.mode, + recursive: true + }).then(() => pth); + } + + const make = pth => { + return mkdir(pth, options.mode) + .then(() => pth) + .catch(error => { + if (error.code === 'EPERM') { + throw error; + } + + if (error.code === 'ENOENT') { + if (path.dirname(pth) === pth) { + throw permissionError(pth); + } + + if (error.message.includes('null bytes')) { + throw error; + } + + return make(path.dirname(pth)).then(() => make(pth)); + } + + return stat(pth) + .then(stats => stats.isDirectory() ? pth : Promise.reject()) + .catch(() => { + throw error; + }); + }); + }; + + return make(path.resolve(input)); +}); + +module.exports = makeDir; +module.exports.default = makeDir; + +module.exports.sync = (input, options) => { + checkPath(input); + options = Object.assign({}, defaults, options); + + if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) { + const pth = path.resolve(input); + + fs.mkdirSync(pth, { + mode: options.mode, + recursive: true + }); + + return pth; + } + + const make = pth => { + try { + options.fs.mkdirSync(pth, options.mode); + } catch (error) { + if (error.code === 'EPERM') { + throw error; + } + + if (error.code === 'ENOENT') { + if (path.dirname(pth) === pth) { + throw permissionError(pth); + } + + if (error.message.includes('null bytes')) { + throw error; + } + + make(path.dirname(pth)); + return make(pth); + } + + try { + if (!options.fs.statSync(pth).isDirectory()) { + throw new Error('The path is not a directory'); + } + } catch (_) { + throw error; + } + } + + return pth; + }; + + return make(path.resolve(input)); +}; + + +/***/ }), +/* 116 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const processFn = (fn, options) => function (...args) { + const P = options.promiseModule; + + return new P((resolve, reject) => { + if (options.multiArgs) { + args.push((...result) => { + if (options.errorFirst) { + if (result[0]) { + reject(result); + } else { + result.shift(); + resolve(result); + } + } else { + resolve(result); + } + }); + } else if (options.errorFirst) { + args.push((error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); + } else { + args.push(resolve); + } + + fn.apply(this, args); + }); +}; + +module.exports = (input, options) => { + options = Object.assign({ + exclude: [/.+(Sync|Stream)$/], + errorFirst: true, + promiseModule: Promise + }, options); + + const objType = typeof input; + if (!(input !== null && (objType === 'object' || objType === 'function'))) { + throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); + } + + const filter = key => { + const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); + return options.include ? options.include.some(match) : !options.exclude.some(match); + }; + + let ret; + if (objType === 'function') { + ret = function (...args) { + return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); + }; + } else { + ret = Object.create(Object.getPrototypeOf(input)); + } + + for (const key in input) { // eslint-disable-line guard-for-in + const property = input[key]; + ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; + } + + return ret; +}; + + +/***/ }), +/* 117 */ +/***/ (function(module, exports) { + +exports = module.exports = SemVer + +var debug +/* istanbul ignore next */ +if (typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG)) { + debug = function () { + var args = Array.prototype.slice.call(arguments, 0) + args.unshift('SEMVER') + console.log.apply(console, args) + } +} else { + debug = function () {} +} + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0' + +var MAX_LENGTH = 256 +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +var MAX_SAFE_COMPONENT_LENGTH = 16 + +// The actual regexps go on exports.re +var re = exports.re = [] +var src = exports.src = [] +var R = 0 + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++ +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' +var NUMERICIDENTIFIERLOOSE = R++ +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++ +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++ +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')' + +var MAINVERSIONLOOSE = R++ +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')' + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++ +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +var PRERELEASEIDENTIFIERLOOSE = R++ +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++ +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' + +var PRERELEASELOOSE = R++ +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++ +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++ +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++ +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?' + +src[FULL] = '^' + FULLPLAIN + '$' + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?' + +var LOOSE = R++ +src[LOOSE] = '^' + LOOSEPLAIN + '$' + +var GTLT = R++ +src[GTLT] = '((?:<|>)?=?)' + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++ +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' +var XRANGEIDENTIFIER = R++ +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' + +var XRANGEPLAIN = R++ +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGEPLAINLOOSE = R++ +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGE = R++ +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' +var XRANGELOOSE = R++ +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +var COERCE = R++ +src[COERCE] = '(?:^|[^\\d])' + + '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:$|[^\\d])' + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++ +src[LONETILDE] = '(?:~>?)' + +var TILDETRIM = R++ +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') +var tildeTrimReplace = '$1~' + +var TILDE = R++ +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' +var TILDELOOSE = R++ +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++ +src[LONECARET] = '(?:\\^)' + +var CARETTRIM = R++ +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') +var caretTrimReplace = '$1^' + +var CARET = R++ +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' +var CARETLOOSE = R++ +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++ +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' +var COMPARATOR = R++ +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++ +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') +var comparatorTrimReplace = '$1$2$3' + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++ +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$' + +var HYPHENRANGELOOSE = R++ +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$' + +// Star ranges basically just allow anything at all. +var STAR = R++ +src[STAR] = '(<|>)?=?\\s*\\*' + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]) + if (!re[i]) { + re[i] = new RegExp(src[i]) + } +} + +exports.parse = parse +function parse (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + if (version.length > MAX_LENGTH) { + return null + } + + var r = options.loose ? re[LOOSE] : re[FULL] + if (!r.test(version)) { + return null + } + + try { + return new SemVer(version, options) + } catch (er) { + return null + } } -Parser.prototype = parser;parser.Parser = Parser; -return new Parser; -})(); +exports.valid = valid +function valid (version, options) { + var v = parse(version, options) + return v ? v.version : null +} -if (true) { -exports.parser = spdxparse; -exports.Parser = spdxparse.Parser; -exports.parse = function () { return spdxparse.parse.apply(spdxparse, arguments); }; -exports.main = function commonjsMain(args) { - if (!args[1]) { - console.log('Usage: '+args[0]+' FILE'); - process.exit(1); +exports.clean = clean +function clean (version, options) { + var s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null +} + +exports.SemVer = SemVer + +function SemVer (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false } - var source = __webpack_require__(23).readFileSync(__webpack_require__(16).normalize(args[1]), "utf8"); - return exports.parser.parse(source); -}; -if ( true && __webpack_require__.c[__webpack_require__.s] === module) { - exports.main(process.argv.slice(1)); + } + if (version instanceof SemVer) { + if (version.loose === options.loose) { + return version + } else { + version = version.version + } + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + } + + if (!(this instanceof SemVer)) { + return new SemVer(version, options) + } + + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + + var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) + + if (!m) { + throw new TypeError('Invalid Version: ' + version) + } + + this.raw = version + + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map(function (id) { + if (/^[0-9]+$/.test(id)) { + var num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) + } + + this.build = m[5] ? m[5].split('.') : [] + this.format() +} + +SemVer.prototype.format = function () { + this.version = this.major + '.' + this.minor + '.' + this.patch + if (this.prerelease.length) { + this.version += '-' + this.prerelease.join('.') + } + return this.version +} + +SemVer.prototype.toString = function () { + return this.version +} + +SemVer.prototype.compare = function (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return this.compareMain(other) || this.comparePre(other) +} + +SemVer.prototype.compareMain = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) +} + +SemVer.prototype.comparePre = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + var i = 0 + do { + var a = this.prerelease[i] + var b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) +} + +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function (release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if (this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + var i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } + } + break + + default: + throw new Error('invalid increment argument: ' + release) + } + this.format() + this.raw = this.version + return this +} + +exports.inc = inc +function inc (version, release, loose, identifier) { + if (typeof (loose) === 'string') { + identifier = loose + loose = undefined + } + + try { + return new SemVer(version, loose).inc(release, identifier).version + } catch (er) { + return null + } +} + +exports.diff = diff +function diff (version1, version2) { + if (eq(version1, version2)) { + return null + } else { + var v1 = parse(version1) + var v2 = parse(version2) + var prefix = '' + if (v1.prerelease.length || v2.prerelease.length) { + prefix = 'pre' + var defaultResult = 'prerelease' + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return prefix + key + } + } + } + return defaultResult // may be undefined + } +} + +exports.compareIdentifiers = compareIdentifiers + +var numeric = /^[0-9]+$/ +function compareIdentifiers (a, b) { + var anum = numeric.test(a) + var bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +} + +exports.rcompareIdentifiers = rcompareIdentifiers +function rcompareIdentifiers (a, b) { + return compareIdentifiers(b, a) +} + +exports.major = major +function major (a, loose) { + return new SemVer(a, loose).major +} + +exports.minor = minor +function minor (a, loose) { + return new SemVer(a, loose).minor +} + +exports.patch = patch +function patch (a, loose) { + return new SemVer(a, loose).patch +} + +exports.compare = compare +function compare (a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)) +} + +exports.compareLoose = compareLoose +function compareLoose (a, b) { + return compare(a, b, true) +} + +exports.rcompare = rcompare +function rcompare (a, b, loose) { + return compare(b, a, loose) +} + +exports.sort = sort +function sort (list, loose) { + return list.sort(function (a, b) { + return exports.compare(a, b, loose) + }) +} + +exports.rsort = rsort +function rsort (list, loose) { + return list.sort(function (a, b) { + return exports.rcompare(a, b, loose) + }) +} + +exports.gt = gt +function gt (a, b, loose) { + return compare(a, b, loose) > 0 +} + +exports.lt = lt +function lt (a, b, loose) { + return compare(a, b, loose) < 0 +} + +exports.eq = eq +function eq (a, b, loose) { + return compare(a, b, loose) === 0 +} + +exports.neq = neq +function neq (a, b, loose) { + return compare(a, b, loose) !== 0 +} + +exports.gte = gte +function gte (a, b, loose) { + return compare(a, b, loose) >= 0 +} + +exports.lte = lte +function lte (a, b, loose) { + return compare(a, b, loose) <= 0 +} + +exports.cmp = cmp +function cmp (a, op, b, loose) { + switch (op) { + case '===': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b + + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b + + case '': + case '=': + case '==': + return eq(a, b, loose) + + case '!=': + return neq(a, b, loose) + + case '>': + return gt(a, b, loose) + + case '>=': + return gte(a, b, loose) + + case '<': + return lt(a, b, loose) + + case '<=': + return lte(a, b, loose) + + default: + throw new TypeError('Invalid operator: ' + op) + } +} + +exports.Comparator = Comparator +function Comparator (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } + + if (!(this instanceof Comparator)) { + return new Comparator(comp, options) + } + + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) + + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version + } + + debug('comp', this) +} + +var ANY = {} +Comparator.prototype.parse = function (comp) { + var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var m = comp.match(r) + + if (!m) { + throw new TypeError('Invalid comparator: ' + comp) + } + + this.operator = m[1] + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } +} + +Comparator.prototype.toString = function () { + return this.value +} + +Comparator.prototype.test = function (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY) { + return true + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + return cmp(version, this.operator, this.semver, this.options) +} + +Comparator.prototype.intersects = function (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + var rangeTmp + + if (this.operator === '') { + rangeTmp = new Range(comp.value, options) + return satisfies(this.value, rangeTmp, options) + } else if (comp.operator === '') { + rangeTmp = new Range(this.value, options) + return satisfies(comp.semver, rangeTmp, options) + } + + var sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>') + var sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<') + var sameSemVer = this.semver.version === comp.semver.version + var differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<=') + var oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, options) && + ((this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<')) + var oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, options) && + ((this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>')) + + return sameDirectionIncreasing || sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan +} + +exports.Range = Range +function Range (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (range instanceof Range) { + if (range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease) { + return range + } else { + return new Range(range.raw, options) + } + } + + if (range instanceof Comparator) { + return new Range(range.value, options) + } + + if (!(this instanceof Range)) { + return new Range(range, options) + } + + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease + + // First, split based on boolean or || + this.raw = range + this.set = range.split(/\s*\|\|\s*/).map(function (range) { + return this.parseRange(range.trim()) + }, this).filter(function (c) { + // throw out any that are not relevant for whatever reason + return c.length + }) + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range) + } + + this.format() +} + +Range.prototype.format = function () { + this.range = this.set.map(function (comps) { + return comps.join(' ').trim() + }).join('||').trim() + return this.range +} + +Range.prototype.toString = function () { + return this.range +} + +Range.prototype.parseRange = function (range) { + var loose = this.options.loose + range = range.trim() + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[COMPARATORTRIM]) + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace) + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace) + + // normalize spaces + range = range.split(/\s+/).join(' ') + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var set = range.split(' ').map(function (comp) { + return parseComparator(comp, this.options) + }, this).join(' ').split(/\s+/) + if (this.options.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function (comp) { + return !!comp.match(compRe) + }) + } + set = set.map(function (comp) { + return new Comparator(comp, this.options) + }, this) + + return set +} + +Range.prototype.intersects = function (range, options) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required') + } + + return this.set.some(function (thisComparators) { + return thisComparators.every(function (thisComparator) { + return range.set.some(function (rangeComparators) { + return rangeComparators.every(function (rangeComparator) { + return thisComparator.intersects(rangeComparator, options) + }) + }) + }) + }) +} + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators +function toComparators (range, options) { + return new Range(range, options).set.map(function (comp) { + return comp.map(function (c) { + return c.value + }).join(' ').trim().split(' ') + }) +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator (comp, options) { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp +} + +function isX (id) { + return !id || id.toLowerCase() === 'x' || id === '*' +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceTilde(comp, options) + }).join(' ') +} + +function replaceTilde (comp, options) { + var r = options.loose ? re[TILDELOOSE] : re[TILDE] + return comp.replace(r, function (_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0 + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else if (pr) { + debug('replaceTilde pr', pr) + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } else { + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + + debug('tilde return', ret) + return ret + }) +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceCaret(comp, options) + }).join(' ') +} + +function replaceCaret (comp, options) { + debug('caret', comp, options) + var r = options.loose ? re[CARETLOOSE] : re[CARET] + return comp.replace(r, function (_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + if (M === '0') { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else { + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' + } + } else if (pr) { + debug('replaceCaret pr', pr) + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + (+M + 1) + '.0.0' + } + } else { + debug('no pr') + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + (+M + 1) + '.0.0' + } + } + + debug('caret return', ret) + return ret + }) } + +function replaceXRanges (comp, options) { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map(function (comp) { + return replaceXRange(comp, options) + }).join(' ') } -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) +function replaceXRange (comp, options) { + comp = comp.trim() + var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] + return comp.replace(r, function (ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + var xM = isX(M) + var xm = xM || isX(m) + var xp = xm || isX(p) + var anyX = xp + + if (gtlt === '=' && anyX) { + gtlt = '' + } + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0' + } else { + // nothing is forbidden + ret = '*' + } + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0 + } + p = 0 + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + // >1.2.3 => >= 1.2.4 + gtlt = '>=' + if (xm) { + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } + } -/***/ }), -/* 71 */ -/***/ (function(module, exports, __webpack_require__) { + ret = gtlt + M + '.' + m + '.' + p + } else if (xm) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (xp) { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } -var licenseIDs = __webpack_require__(72); + debug('xRange return', ret) -function valid(string) { - return licenseIDs.indexOf(string) > -1; + return ret + }) } -// Common transpositions of license identifier acronyms -var transpositions = [ - ['APGL', 'AGPL'], - ['Gpl', 'GPL'], - ['GLP', 'GPL'], - ['APL', 'Apache'], - ['ISD', 'ISC'], - ['GLP', 'GPL'], - ['IST', 'ISC'], - ['Claude', 'Clause'], - [' or later', '+'], - [' International', ''], - ['GNU', 'GPL'], - ['GUN', 'GPL'], - ['+', ''], - ['GNU GPL', 'GPL'], - ['GNU/GPL', 'GPL'], - ['GNU GLP', 'GPL'], - ['GNU General Public License', 'GPL'], - ['Gnu public license', 'GPL'], - ['GNU Public License', 'GPL'], - ['GNU GENERAL PUBLIC LICENSE', 'GPL'], - ['MTI', 'MIT'], - ['Mozilla Public License', 'MPL'], - ['WTH', 'WTF'], - ['-License', ''] -]; +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars (comp, options) { + debug('replaceStars', comp, options) + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], '') +} -var TRANSPOSED = 0; -var CORRECT = 1; +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +function hyphenReplace ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = '>=' + fM + '.0.0' + } else if (isX(fp)) { + from = '>=' + fM + '.' + fm + '.0' + } else { + from = '>=' + from + } -// Simple corrections to nearly valid identifiers. -var transforms = [ - // e.g. 'mit' - function(argument) { - return argument.toUpperCase(); - }, - // e.g. 'MIT ' - function(argument) { - return argument.trim(); - }, - // e.g. 'M.I.T.' - function(argument) { - return argument.replace(/\./g, ''); - }, - // e.g. 'Apache- 2.0' - function(argument) { - return argument.replace(/\s+/g, ''); - }, - // e.g. 'CC BY 4.0'' - function(argument) { - return argument.replace(/\s+/g, '-'); - }, - // e.g. 'LGPLv2.1' - function(argument) { - return argument.replace('v', '-'); - }, - // e.g. 'Apache 2.0' - function(argument) { - return argument.replace(/,?\s*(\d)/, '-$1'); - }, - // e.g. 'GPL 2' - function(argument) { - return argument.replace(/,?\s*(\d)/, '-$1.0'); - }, - // e.g. 'Apache Version 2.0' - function(argument) { - return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2'); - }, - // e.g. 'Apache Version 2' - function(argument) { - return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2.0'); - }, - // e.g. 'ZLIB' - function(argument) { - return argument[0].toUpperCase() + argument.slice(1); - }, - // e.g. 'MPL/2.0' - function(argument) { - return argument.replace('/', '-'); - }, - // e.g. 'Apache 2' - function(argument) { - return argument - .replace(/\s*V\s*(\d)/, '-$1') - .replace(/(\d)$/, '$1.0'); - }, - // e.g. 'GPL-2.0-' - function(argument) { - return argument.slice(0, argument.length - 1); - }, - // e.g. 'GPL2' - function(argument) { - return argument.replace(/(\d)$/, '-$1.0'); - }, - // e.g. 'BSD 3' - function(argument) { - return argument.replace(/(-| )?(\d)$/, '-$2-Clause'); - }, - // e.g. 'BSD clause 3' - function(argument) { - return argument.replace(/(-| )clause(-| )(\d)/, '-$3-Clause'); - }, - // e.g. 'BY-NC-4.0' - function(argument) { - return 'CC-' + argument; - }, - // e.g. 'BY-NC' - function(argument) { - return 'CC-' + argument + '-4.0'; - }, - // e.g. 'Attribution-NonCommercial' - function(argument) { - return argument - .replace('Attribution', 'BY') - .replace('NonCommercial', 'NC') - .replace('NoDerivatives', 'ND') - .replace(/ (\d)/, '-$1') - .replace(/ ?International/, ''); - }, - // e.g. 'Attribution-NonCommercial' - function(argument) { - return 'CC-' + - argument - .replace('Attribution', 'BY') - .replace('NonCommercial', 'NC') - .replace('NoDerivatives', 'ND') - .replace(/ (\d)/, '-$1') - .replace(/ ?International/, '') + - '-4.0'; + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = '<' + (+tM + 1) + '.0.0' + } else if (isX(tp)) { + to = '<' + tM + '.' + (+tm + 1) + '.0' + } else if (tpr) { + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr + } else { + to = '<=' + to } -]; -// If all else fails, guess that strings containing certain substrings -// meant to identify certain licenses. -var lastResorts = [ - ['UNLI', 'Unlicense'], - ['WTF', 'WTFPL'], - ['2 CLAUSE', 'BSD-2-Clause'], - ['2-CLAUSE', 'BSD-2-Clause'], - ['3 CLAUSE', 'BSD-3-Clause'], - ['3-CLAUSE', 'BSD-3-Clause'], - ['AFFERO', 'AGPL-3.0'], - ['AGPL', 'AGPL-3.0'], - ['APACHE', 'Apache-2.0'], - ['ARTISTIC', 'Artistic-2.0'], - ['Affero', 'AGPL-3.0'], - ['BEER', 'Beerware'], - ['BOOST', 'BSL-1.0'], - ['BSD', 'BSD-2-Clause'], - ['ECLIPSE', 'EPL-1.0'], - ['FUCK', 'WTFPL'], - ['GNU', 'GPL-3.0'], - ['LGPL', 'LGPL-3.0'], - ['GPL', 'GPL-3.0'], - ['MIT', 'MIT'], - ['MPL', 'MPL-2.0'], - ['X11', 'X11'], - ['ZLIB', 'Zlib'] -]; + return (from + ' ' + to).trim() +} -var SUBSTRING = 0; -var IDENTIFIER = 1; +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function (version) { + if (!version) { + return false + } -var validTransformation = function(identifier) { - for (var i = 0; i < transforms.length; i++) { - var transformed = transforms[i](identifier); - if (transformed !== identifier && valid(transformed)) { - return transformed; + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true } } - return null; -}; + return false +} -var validLastResort = function(identifier) { - var upperCased = identifier.toUpperCase(); - for (var i = 0; i < lastResorts.length; i++) { - var lastResort = lastResorts[i]; - if (upperCased.indexOf(lastResort[SUBSTRING]) > -1) { - return lastResort[IDENTIFIER]; +function testSet (set, version, options) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false } } - return null; -}; -var anyCorrection = function(identifier, check) { - for (var i = 0; i < transpositions.length; i++) { - var transposition = transpositions[i]; - var transposed = transposition[TRANSPOSED]; - if (identifier.indexOf(transposed) > -1) { - var corrected = identifier.replace( - transposed, - transposition[CORRECT] - ); - var checked = check(corrected); - if (checked !== null) { - return checked; + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === ANY) { + continue + } + + if (set[i].semver.prerelease.length > 0) { + var allowed = set[i].semver + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } } } + + // Version has a -pre, but it's not one of the ones we like. + return false } - return null; -}; -module.exports = function(identifier) { - identifier = identifier.replace(/\+$/, ''); - if (valid(identifier)) { - return identifier; + return true +} + +exports.satisfies = satisfies +function satisfies (version, range, options) { + try { + range = new Range(range, options) + } catch (er) { + return false } - var transformed = validTransformation(identifier); - if (transformed !== null) { - return transformed; + return range.test(version) +} + +exports.maxSatisfying = maxSatisfying +function maxSatisfying (versions, range, options) { + var max = null + var maxSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null } - transformed = anyCorrection(identifier, function(argument) { - if (valid(argument)) { - return argument; + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) + } } - return validTransformation(argument); - }); - if (transformed !== null) { - return transformed; - } - transformed = validLastResort(identifier); - if (transformed !== null) { - return transformed; - } - transformed = anyCorrection(identifier, validLastResort); - if (transformed !== null) { - return transformed; + }) + return max +} + +exports.minSatisfying = minSatisfying +function minSatisfying (versions, range, options) { + var min = null + var minSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null } - return null; -}; + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) + } + } + }) + return min +} +exports.minVersion = minVersion +function minVersion (range, loose) { + range = new Range(range, loose) -/***/ }), -/* 72 */ -/***/ (function(module) { + var minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } -module.exports = ["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"]; + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } -/***/ }), -/* 73 */ -/***/ (function(module, exports, __webpack_require__) { + minver = null + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + comparators.forEach(function (comparator) { + // Clone to avoid manipulating the comparator's semver object. + var compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error('Unexpected operation: ' + comparator.operator) + } + }) + } -"use strict"; + if (minver && range.test(minver)) { + return minver + } -var url = __webpack_require__(74) -var gitHosts = __webpack_require__(75) -var GitHost = module.exports = __webpack_require__(76) + return null +} -var protocolToRepresentationMap = { - 'git+ssh': 'sshurl', - 'git+https': 'https', - 'ssh': 'sshurl', - 'git': 'git' +exports.validRange = validRange +function validRange (range, options) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, options).range || '*' + } catch (er) { + return null + } } -function protocolToRepresentation (protocol) { - if (protocol.substr(-1) === ':') protocol = protocol.slice(0, -1) - return protocolToRepresentationMap[protocol] || protocol +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr +function ltr (version, range, options) { + return outside(version, range, '<', options) } -var authProtocols = { - 'git:': true, - 'https:': true, - 'git+https:': true, - 'http:': true, - 'git+http:': true +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr +function gtr (version, range, options) { + return outside(version, range, '>', options) } -var cache = {} +exports.outside = outside +function outside (version, range, hilo, options) { + version = new SemVer(version, options) + range = new Range(range, options) -module.exports.fromUrl = function (giturl, opts) { - var key = giturl + JSON.stringify(opts || {}) + var gtfn, ltefn, ltfn, comp, ecomp + switch (hilo) { + case '>': + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break + case '<': + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } - if (!(key in cache)) { - cache[key] = fromUrl(giturl, opts) + // If it satisifes the range it is not outside + if (satisfies(version, range, options)) { + return false } - return cache[key] -} + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. -function fromUrl (giturl, opts) { - if (giturl == null || giturl === '') return - var url = fixupUnqualifiedGist( - isGitHubShorthand(giturl) ? 'github:' + giturl : giturl - ) - var parsed = parseGitUrl(url) - var shortcutMatch = url.match(new RegExp('^([^:]+):(?:(?:[^@:]+(?:[^@]+)?@)?([^/]*))[/](.+?)(?:[.]git)?($|#)')) - var matches = Object.keys(gitHosts).map(function (gitHostName) { - try { - var gitHostInfo = gitHosts[gitHostName] - var auth = null - if (parsed.auth && authProtocols[parsed.protocol]) { - auth = decodeURIComponent(parsed.auth) + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + var high = null + var low = null + + comparators.forEach(function (comparator) { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') } - var committish = parsed.hash ? decodeURIComponent(parsed.hash.substr(1)) : null - var user = null - var project = null - var defaultRepresentation = null - if (shortcutMatch && shortcutMatch[1] === gitHostName) { - user = shortcutMatch[2] && decodeURIComponent(shortcutMatch[2]) - project = decodeURIComponent(shortcutMatch[3]) - defaultRepresentation = 'shortcut' - } else { - if (parsed.host !== gitHostInfo.domain) return - if (!gitHostInfo.protocols_re.test(parsed.protocol)) return - if (!parsed.path) return - var pathmatch = gitHostInfo.pathmatch - var matched = parsed.path.match(pathmatch) - if (!matched) return - if (matched[1] != null) user = decodeURIComponent(matched[1].replace(/^:/, '')) - if (matched[2] != null) project = decodeURIComponent(matched[2]) - defaultRepresentation = protocolToRepresentation(parsed.protocol) + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator } - return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts) - } catch (ex) { - if (!(ex instanceof URIError)) throw ex + }) + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false } - }).filter(function (gitHostInfo) { return gitHostInfo }) - if (matches.length !== 1) return - return matches[0] + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true } -function isGitHubShorthand (arg) { - // Note: This does not fully test the git ref format. - // See https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html - // - // The only way to do this properly would be to shell out to - // git-check-ref-format, and as this is a fast sync function, - // we don't want to do that. Just let git fail if it turns - // out that the commit-ish is invalid. - // GH usernames cannot start with . or - - return /^[^:@%/\s.-][^:@%/\s]*[/][^:@\s/%]+(?:#.*)?$/.test(arg) +exports.prerelease = prerelease +function prerelease (version, options) { + var parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null } -function fixupUnqualifiedGist (giturl) { - // necessary for round-tripping gists - var parsed = url.parse(giturl) - if (parsed.protocol === 'gist:' && parsed.host && !parsed.path) { - return parsed.protocol + '/' + parsed.host - } else { - return giturl +exports.intersects = intersects +function intersects (r1, r2, options) { + r1 = new Range(r1, options) + r2 = new Range(r2, options) + return r1.intersects(r2) +} + +exports.coerce = coerce +function coerce (version) { + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null } + + var match = version.match(re[COERCE]) + + if (match == null) { + return null + } + + return parse(match[1] + + '.' + (match[2] || '0') + + '.' + (match[3] || '0')) +} + + +/***/ }), +/* 118 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +// detect either spaces or tabs but not both to properly handle tabs +// for indentation and spaces for alignment +const INDENT_RE = /^(?:( )+|\t+)/; + +function getMostUsed(indents) { + let result = 0; + let maxUsed = 0; + let maxWeight = 0; + + for (const entry of indents) { + // TODO: use destructuring when targeting Node.js 6 + const key = entry[0]; + const val = entry[1]; + + const u = val[0]; + const w = val[1]; + + if (u > maxUsed || (u === maxUsed && w > maxWeight)) { + maxUsed = u; + maxWeight = w; + result = Number(key); + } + } + + return result; } -function parseGitUrl (giturl) { - if (typeof giturl !== 'string') giturl = '' + giturl - var matched = giturl.match(/^([^@]+)@([^:/]+):[/]?((?:[^/]+[/])?[^/]+?)(?:[.]git)?(#.*)?$/) - if (!matched) return url.parse(giturl) - return { - protocol: 'git+ssh:', - slashes: true, - auth: matched[1], - host: matched[2], - port: null, - hostname: matched[2], - hash: matched[4], - search: null, - query: null, - pathname: '/' + matched[3], - path: '/' + matched[3], - href: 'git+ssh://' + matched[1] + '@' + matched[2] + - '/' + matched[3] + (matched[4] || '') - } -} +module.exports = str => { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + // used to see if tabs or spaces are the most used + let tabs = 0; + let spaces = 0; + + // remember the size of previous line's indentation + let prev = 0; + + // remember how many indents/unindents as occurred for a given size + // and how much lines follow a given indentation + // + // indents = { + // 3: [1, 0], + // 4: [1, 5], + // 5: [1, 0], + // 12: [1, 0], + // } + const indents = new Map(); + + // pointer to the array of last used indent + let current; + + // whether the last action was an indent (opposed to an unindent) + let isIndent; + + for (const line of str.split(/\n/g)) { + if (!line) { + // ignore empty lines + continue; + } + + let indent; + const matches = line.match(INDENT_RE); + if (matches) { + indent = matches[0].length; -/***/ }), -/* 74 */ -/***/ (function(module, exports) { + if (matches[1]) { + spaces++; + } else { + tabs++; + } + } else { + indent = 0; + } -module.exports = require("url"); + const diff = indent - prev; + prev = indent; -/***/ }), -/* 75 */ -/***/ (function(module, exports, __webpack_require__) { + if (diff) { + // an indent or unindent has been detected -"use strict"; + isIndent = diff > 0; + current = indents.get(isIndent ? diff : -diff); -var gitHosts = module.exports = { - github: { - // First two are insecure and generally shouldn't be used any more, but - // they are still supported. - 'protocols': [ 'git', 'http', 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'github.com', - 'treepath': 'tree', - 'filetemplate': 'https://{auth@}raw.githubusercontent.com/{user}/{project}/{committish}/{path}', - 'bugstemplate': 'https://{domain}/{user}/{project}/issues', - 'gittemplate': 'git://{auth@}{domain}/{user}/{project}.git{#committish}', - 'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz' - }, - bitbucket: { - 'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'bitbucket.org', - 'treepath': 'src', - 'tarballtemplate': 'https://{domain}/{user}/{project}/get/{committish}.tar.gz' - }, - gitlab: { - 'protocols': [ 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'gitlab.com', - 'treepath': 'tree', - 'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#README', - 'bugstemplate': 'https://{domain}/{user}/{project}/issues', - 'tarballtemplate': 'https://{domain}/{user}/{project}/repository/archive.tar.gz?ref={committish}' - }, - gist: { - 'protocols': [ 'git', 'git+ssh', 'git+https', 'ssh', 'https' ], - 'domain': 'gist.github.com', - 'pathmatch': /^[/](?:([^/]+)[/])?([a-z0-9]+)(?:[.]git)?$/, - 'filetemplate': 'https://gist.githubusercontent.com/{user}/{project}/raw{/committish}/{path}', - 'bugstemplate': 'https://{domain}/{project}', - 'gittemplate': 'git://{domain}/{project}.git{#committish}', - 'sshtemplate': 'git@{domain}:/{project}.git{#committish}', - 'sshurltemplate': 'git+ssh://git@{domain}/{project}.git{#committish}', - 'browsetemplate': 'https://{domain}/{project}{/committish}', - 'docstemplate': 'https://{domain}/{project}{/committish}', - 'httpstemplate': 'git+https://{domain}/{project}.git{#committish}', - 'shortcuttemplate': '{type}:{project}{#committish}', - 'pathtemplate': '{project}{#committish}', - 'tarballtemplate': 'https://{domain}/{user}/{project}/archive/{committish}.tar.gz' - } -} + if (current) { + current[0]++; + } else { + current = [1, 0]; + indents.set(diff, current); + } + } else if (current) { + // if the last action was an indent, increment the weight + current[1] += Number(isIndent); + } + } -var gitHostDefaults = { - 'sshtemplate': 'git@{domain}:{user}/{project}.git{#committish}', - 'sshurltemplate': 'git+ssh://git@{domain}/{user}/{project}.git{#committish}', - 'browsetemplate': 'https://{domain}/{user}/{project}{/tree/committish}', - 'docstemplate': 'https://{domain}/{user}/{project}{/tree/committish}#readme', - 'httpstemplate': 'git+https://{auth@}{domain}/{user}/{project}.git{#committish}', - 'filetemplate': 'https://{domain}/{user}/{project}/raw/{committish}/{path}', - 'shortcuttemplate': '{type}:{user}/{project}{#committish}', - 'pathtemplate': '{user}/{project}{#committish}', - 'pathmatch': /^[/]([^/]+)[/]([^/]+?)(?:[.]git|[/])?$/ -} + const amount = getMostUsed(indents); -Object.keys(gitHosts).forEach(function (name) { - Object.keys(gitHostDefaults).forEach(function (key) { - if (gitHosts[name][key]) return - gitHosts[name][key] = gitHostDefaults[key] - }) - gitHosts[name].protocols_re = RegExp('^(' + - gitHosts[name].protocols.map(function (protocol) { - return protocol.replace(/([\\+*{}()[\]$^|])/g, '\\$1') - }).join('|') + '):$') -}) + let type; + let indent; + if (!amount) { + type = null; + indent = ''; + } else if (spaces >= tabs) { + type = 'space'; + indent = ' '.repeat(amount); + } else { + type = 'tab'; + indent = '\t'.repeat(amount); + } + + return { + amount, + type, + indent + }; +}; /***/ }), -/* 76 */ -/***/ (function(module, exports, __webpack_require__) { +/* 119 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "installInDir", function() { return installInDir; }); +/* 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__(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. + */ -var gitHosts = __webpack_require__(75) -var extend = Object.assign || __webpack_require__(29)._extend -var GitHost = module.exports = function (type, user, auth, project, committish, defaultRepresentation, opts) { - var gitHostInfo = this - gitHostInfo.type = type - Object.keys(gitHosts[type]).forEach(function (key) { - gitHostInfo[key] = gitHosts[type][key] - }) - gitHostInfo.user = user - gitHostInfo.auth = auth - gitHostInfo.project = project - gitHostInfo.committish = committish - gitHostInfo.default = defaultRepresentation - gitHostInfo.opts = opts || {} -} -GitHost.prototype = {} +/** + * Install all dependencies in the given directory + */ +async function installInDir(directory, extraArgs = []) { + const options = ['install', '--non-interactive', ...extraArgs]; // We pass the mutex flag to ensure only one instance of yarn runs at any + // given time (e.g. to avoid conflicts). -GitHost.prototype.hash = function () { - return this.committish ? '#' + this.committish : '' + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', options, { + cwd: directory + }); } +/** + * Run script in the given directory + */ -GitHost.prototype._fill = function (template, opts) { - if (!template) return - var vars = extend({}, opts) - opts = extend(extend({}, this.opts), opts) - var self = this - Object.keys(this).forEach(function (key) { - if (self[key] != null && vars[key] == null) vars[key] = self[key] - }) - var rawAuth = vars.auth - var rawComittish = vars.committish - Object.keys(vars).forEach(function (key) { - vars[key] = encodeURIComponent(vars[key]) - }) - vars['auth@'] = rawAuth ? rawAuth + '@' : '' - if (opts.noCommittish) { - vars['#committish'] = '' - vars['/tree/committish'] = '' - vars['/comittish'] = '' - vars.comittish = '' - } else { - vars['#committish'] = rawComittish ? '#' + rawComittish : '' - vars['/tree/committish'] = vars.committish - ? '/' + vars.treepath + '/' + vars.committish - : '' - vars['/committish'] = vars.committish ? '/' + vars.committish : '' - vars.committish = vars.committish || 'master' - } - var res = template - Object.keys(vars).forEach(function (key) { - res = res.replace(new RegExp('[{]' + key + '[}]', 'g'), vars[key]) - }) - if (opts.noGitPlus) { - return res.replace(/^git[+]/, '') - } else { - return res - } +async function runScriptInPackage(script, args, pkg) { + const execOpts = { + cwd: pkg.path + }; + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['run', script, ...args], execOpts); } +/** + * Run script in the given directory + */ -GitHost.prototype.ssh = function (opts) { - return this._fill(this.sshtemplate, opts) +function runScriptInPackageStreaming(script, args, pkg) { + const execOpts = { + cwd: pkg.path + }; + return Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawnStreaming"])('yarn', ['run', script, ...args], execOpts, { + prefix: pkg.name + }); } - -GitHost.prototype.sshurl = function (opts) { - return this._fill(this.sshurltemplate, opts) +async function yarnWorkspacesInfo(directory) { + const workspacesInfo = await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['workspaces', 'info', '--json'], { + cwd: directory, + stdio: 'pipe' + }); + const stdout = JSON.parse(workspacesInfo.stdout); + return JSON.parse(stdout.data); } -GitHost.prototype.browse = function (opts) { - return this._fill(this.browsetemplate, opts) -} +/***/ }), +/* 120 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -GitHost.prototype.docs = function (opts) { - return this._fill(this.docstemplate, opts) -} +"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 chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(121); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(149); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(154); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); +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; } -GitHost.prototype.bugs = function (opts) { - return this._fill(this.bugstemplate, opts) -} +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } -GitHost.prototype.https = function (opts) { - return this._fill(this.httpstemplate, opts) -} +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; } -GitHost.prototype.git = function (opts) { - return this._fill(this.gittemplate, opts) -} +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -GitHost.prototype.shortcut = function (opts) { - return this._fill(this.shortcuttemplate, opts) -} -GitHost.prototype.path = function (opts) { - return this._fill(this.pathtemplate, opts) -} -GitHost.prototype.tarball = function (opts) { - return this._fill(this.tarballtemplate, opts) -} -GitHost.prototype.file = function (P, opts) { - return this._fill(this.filetemplate, extend({ - path: P.replace(/^[/]+/g, '') - }, opts)) -} -GitHost.prototype.getDefaultRepresentation = function () { - return this.default +function generateColors() { + const colorWheel = [chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.magenta, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.blue, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.yellow, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green]; + const count = colorWheel.length; + let children = 0; + return () => colorWheel[children++ % count]; } -GitHost.prototype.toString = function (opts) { - return (this[this.default] || this.sshurl).call(this, opts) +function spawn(command, args, opts) { + return execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({ + stdio: 'inherit' + }, opts)); +} +const nextColor = generateColors(); +function spawnStreaming(command, args, opts, { + prefix +}) { + const spawned = execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({ + stdio: ['ignore', 'pipe', 'pipe'] + }, opts)); + const color = nextColor(); + const prefixedStdout = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ + tag: `${color.bold(prefix)}:` + }); + const prefixedStderr = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ + mergeMultiline: true, + tag: `${log_symbols__WEBPACK_IMPORTED_MODULE_2___default.a.error} ${color.bold(prefix)}:` + }); + spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); + spawned.stderr.pipe(prefixedStderr).pipe(process.stderr); + return spawned; } - /***/ }), -/* 77 */ +/* 121 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var builtinModules = __webpack_require__(78); +const path = __webpack_require__(16); +const childProcess = __webpack_require__(122); +const crossSpawn = __webpack_require__(123); +const stripEof = __webpack_require__(138); +const npmRunPath = __webpack_require__(139); +const isStream = __webpack_require__(141); +const _getStream = __webpack_require__(142); +const pFinally = __webpack_require__(146); +const onExit = __webpack_require__(110); +const errname = __webpack_require__(147); +const stdio = __webpack_require__(148); -module.exports = function (str) { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } +const TEN_MEGABYTES = 1000 * 1000 * 10; - return builtinModules.indexOf(str) !== -1; -}; +function handleArgs(cmd, args, opts) { + let parsed; + opts = Object.assign({ + extendEnv: true, + env: {} + }, opts); -/***/ }), -/* 78 */ -/***/ (function(module, exports, __webpack_require__) { + if (opts.extendEnv) { + opts.env = Object.assign({}, process.env, opts.env); + } -"use strict"; + if (opts.__winShell === true) { + delete opts.__winShell; + parsed = { + command: cmd, + args, + options: opts, + file: cmd, + original: { + cmd, + args + } + }; + } else { + parsed = crossSpawn._parse(cmd, args, opts); + } + opts = Object.assign({ + maxBuffer: TEN_MEGABYTES, + buffer: true, + stripEof: true, + preferLocal: true, + localDir: parsed.options.cwd || process.cwd(), + encoding: 'utf8', + reject: true, + cleanup: true + }, parsed.options); -var blacklist = [ - 'freelist', - 'sys' -]; + opts.stdio = stdio(opts); -module.exports = Object.keys(process.binding('natives')).filter(function (el) { - return !/^_|^internal|\//.test(el) && blacklist.indexOf(el) === -1; -}).sort(); + if (opts.preferLocal) { + opts.env = npmRunPath.env(Object.assign({}, opts, {cwd: opts.localDir})); + } + if (opts.detached) { + // #115 + opts.cleanup = false; + } -/***/ }), -/* 79 */ -/***/ (function(module, exports) { + if (process.platform === 'win32' && path.basename(parsed.command) === 'cmd.exe') { + // #116 + parsed.args.unshift('/q'); + } -module.exports = extractDescription + return { + cmd: parsed.command, + args: parsed.args, + opts, + parsed + }; +} -// Extracts description from contents of a readme file in markdown format -function extractDescription (d) { - if (!d) return; - if (d === "ERROR: No README data found!") return; - // the first block of text before the first heading - // that isn't the first line heading - d = d.trim().split('\n') - for (var s = 0; d[s] && d[s].trim().match(/^(#|$)/); s ++); - var l = d.length - for (var e = s + 1; e < l && d[e].trim(); e ++); - return d.slice(s, e).join(' ').trim() +function handleInput(spawned, input) { + if (input === null || input === undefined) { + return; + } + + if (isStream(input)) { + input.pipe(spawned.stdin); + } else { + spawned.stdin.end(input); + } } +function handleOutput(opts, val) { + if (val && opts.stripEof) { + val = stripEof(val); + } -/***/ }), -/* 80 */ -/***/ (function(module) { + return val; +} -module.exports = {"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"}}; +function handleShell(fn, cmd, opts) { + let file = '/bin/sh'; + let args = ['-c', cmd]; -/***/ }), -/* 81 */ -/***/ (function(module, exports, __webpack_require__) { + opts = Object.assign({}, opts); -var util = __webpack_require__(29) -var messages = __webpack_require__(82) + if (process.platform === 'win32') { + opts.__winShell = true; + file = process.env.comspec || 'cmd.exe'; + args = ['/s', '/c', `"${cmd}"`]; + opts.windowsVerbatimArguments = true; + } -module.exports = function() { - var args = Array.prototype.slice.call(arguments, 0) - var warningName = args.shift() - if (warningName == "typo") { - return makeTypoWarning.apply(null,args) - } - else { - var msgTemplate = messages[warningName] ? messages[warningName] : warningName + ": '%s'" - args.unshift(msgTemplate) - return util.format.apply(null, args) - } -} + if (opts.shell) { + file = opts.shell; + delete opts.shell; + } -function makeTypoWarning (providedName, probableName, field) { - if (field) { - providedName = field + "['" + providedName + "']" - probableName = field + "['" + probableName + "']" - } - return util.format(messages.typo, providedName, probableName) + return fn(file, args, opts); } +function getStream(process, stream, {encoding, buffer, maxBuffer}) { + if (!process[stream]) { + return null; + } -/***/ }), -/* 82 */ -/***/ (function(module) { + let ret; -module.exports = {"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."}; + if (!buffer) { + // TODO: Use `ret = util.promisify(stream.finished)(process[stream]);` when targeting Node.js 10 + ret = new Promise((resolve, reject) => { + process[stream] + .once('end', resolve) + .once('error', reject); + }); + } else if (encoding) { + ret = _getStream(process[stream], { + encoding, + maxBuffer + }); + } else { + ret = _getStream.buffer(process[stream], {maxBuffer}); + } -/***/ }), -/* 83 */ -/***/ (function(module, exports, __webpack_require__) { + return ret.catch(err => { + err.stream = stream; + err.message = `${stream} ${err.message}`; + throw err; + }); +} -"use strict"; +function makeError(result, options) { + const {stdout, stderr} = result; -const path = __webpack_require__(16); -const writeJsonFile = __webpack_require__(84); -const sortKeys = __webpack_require__(89); + let err = result.error; + const {code, signal} = result; -const opts = {detectIndent: true}; + const {parsed, joinedCmd} = options; + const timedOut = options.timedOut || false; -const dependencyKeys = new Set([ - 'dependencies', - 'devDependencies', - 'optionalDependencies', - 'peerDependencies' -]); + if (!err) { + let output = ''; -function normalize(pkg) { - const ret = {}; + if (Array.isArray(parsed.opts.stdio)) { + if (parsed.opts.stdio[2] !== 'inherit') { + output += output.length > 0 ? stderr : `\n${stderr}`; + } - for (const key of Object.keys(pkg)) { - if (!dependencyKeys.has(key)) { - ret[key] = pkg[key]; - } else if (Object.keys(pkg[key]).length !== 0) { - ret[key] = sortKeys(pkg[key]); + if (parsed.opts.stdio[1] !== 'inherit') { + output += `\n${stdout}`; + } + } else if (parsed.opts.stdio !== 'inherit') { + output = `\n${stderr}${stdout}`; } - } - - return ret; -} -module.exports = (fp, data) => { - if (typeof fp !== 'string') { - data = fp; - fp = '.'; + err = new Error(`Command failed: ${joinedCmd}${output}`); + err.code = code < 0 ? errname(code) : code; } - fp = path.basename(fp) === 'package.json' ? fp : path.join(fp, 'package.json'); + err.stdout = stdout; + err.stderr = stderr; + err.failed = true; + err.signal = signal || null; + err.cmd = joinedCmd; + err.timedOut = timedOut; - data = normalize(data); + return err; +} - return writeJsonFile(fp, data, opts); -}; +function joinCmd(cmd, args) { + let joinedCmd = cmd; -module.exports.sync = (fp, data) => { - if (typeof fp !== 'string') { - data = fp; - fp = '.'; + if (Array.isArray(args) && args.length > 0) { + joinedCmd += ' ' + args.join(' '); } - fp = path.basename(fp) === 'package.json' ? fp : path.join(fp, 'package.json'); + return joinedCmd; +} - data = normalize(data); +module.exports = (cmd, args, opts) => { + const parsed = handleArgs(cmd, args, opts); + const {encoding, buffer, maxBuffer} = parsed.opts; + const joinedCmd = joinCmd(cmd, args); - writeJsonFile.sync(fp, data, opts); -}; + let spawned; + try { + spawned = childProcess.spawn(parsed.cmd, parsed.args, parsed.opts); + } catch (err) { + return Promise.reject(err); + } + let removeExitHandler; + if (parsed.opts.cleanup) { + removeExitHandler = onExit(() => { + spawned.kill(); + }); + } -/***/ }), -/* 84 */ -/***/ (function(module, exports, __webpack_require__) { + let timeoutId = null; + let timedOut = false; -"use strict"; + const cleanup = () => { + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = null; + } -const path = __webpack_require__(16); -const fs = __webpack_require__(22); -const writeFileAtomic = __webpack_require__(85); -const sortKeys = __webpack_require__(89); -const makeDir = __webpack_require__(91); -const pify = __webpack_require__(93); -const detectIndent = __webpack_require__(94); - -const init = (fn, fp, data, opts) => { - if (!fp) { - throw new TypeError('Expected a filepath'); - } + if (removeExitHandler) { + removeExitHandler(); + } + }; - if (data === undefined) { - throw new TypeError('Expected data to stringify'); + if (parsed.opts.timeout > 0) { + timeoutId = setTimeout(() => { + timeoutId = null; + timedOut = true; + spawned.kill(parsed.opts.killSignal); + }, parsed.opts.timeout); } - opts = Object.assign({ - indent: '\t', - sortKeys: false - }, opts); + const processDone = new Promise(resolve => { + spawned.on('exit', (code, signal) => { + cleanup(); + resolve({code, signal}); + }); - if (opts.sortKeys) { - data = sortKeys(data, { - deep: true, - compare: typeof opts.sortKeys === 'function' && opts.sortKeys + spawned.on('error', err => { + cleanup(); + resolve({error: err}); }); - } - return fn(fp, data, opts); -}; + if (spawned.stdin) { + spawned.stdin.on('error', err => { + cleanup(); + resolve({error: err}); + }); + } + }); -const readFile = fp => pify(fs.readFile)(fp, 'utf8').catch(() => {}); + function destroy() { + if (spawned.stdout) { + spawned.stdout.destroy(); + } -const main = (fp, data, opts) => { - return (opts.detectIndent ? readFile(fp) : Promise.resolve()) - .then(str => { - const indent = str ? detectIndent(str).indent : opts.indent; - const json = JSON.stringify(data, opts.replacer, indent); + if (spawned.stderr) { + spawned.stderr.destroy(); + } + } - return pify(writeFileAtomic)(fp, `${json}\n`, {mode: opts.mode}); - }); -}; + const handlePromise = () => pFinally(Promise.all([ + processDone, + getStream(spawned, 'stdout', {encoding, buffer, maxBuffer}), + getStream(spawned, 'stderr', {encoding, buffer, maxBuffer}) + ]).then(arr => { + const result = arr[0]; + result.stdout = arr[1]; + result.stderr = arr[2]; -const mainSync = (fp, data, opts) => { - let indent = opts.indent; + if (result.error || result.code !== 0 || result.signal !== null) { + const err = makeError(result, { + joinedCmd, + parsed, + timedOut + }); - if (opts.detectIndent) { - try { - const file = fs.readFileSync(fp, 'utf8'); - indent = detectIndent(file).indent; - } catch (err) { - if (err.code !== 'ENOENT') { - throw err; + // TODO: missing some timeout logic for killed + // https://github.com/nodejs/node/blob/master/lib/child_process.js#L203 + // err.killed = spawned.killed || killed; + err.killed = err.killed || spawned.killed; + + if (!parsed.opts.reject) { + return err; } - } - } - const json = JSON.stringify(data, opts.replacer, indent); + throw err; + } - return writeFileAtomic.sync(fp, `${json}\n`, {mode: opts.mode}); -}; + return { + stdout: handleOutput(parsed.opts, result.stdout), + stderr: handleOutput(parsed.opts, result.stderr), + code: 0, + failed: false, + killed: false, + signal: null, + cmd: joinedCmd, + timedOut: false + }; + }), destroy); -module.exports = (fp, data, opts) => { - return makeDir(path.dirname(fp), {fs}) - .then(() => init(main, fp, data, opts)); -}; + crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); -module.exports.sync = (fp, data, opts) => { - makeDir.sync(path.dirname(fp), {fs}); - init(mainSync, fp, data, opts); -}; + handleInput(spawned, parsed.opts.input); + spawned.then = (onfulfilled, onrejected) => handlePromise().then(onfulfilled, onrejected); + spawned.catch = onrejected => handlePromise().catch(onrejected); -/***/ }), -/* 85 */ -/***/ (function(module, exports, __webpack_require__) { + return spawned; +}; -"use strict"; +// TODO: set `stderr: 'ignore'` when that option is implemented +module.exports.stdout = (...args) => module.exports(...args).then(x => x.stdout); -module.exports = writeFile -module.exports.sync = writeFileSync -module.exports._getTmpname = getTmpname // for testing -module.exports._cleanupOnExit = cleanupOnExit +// TODO: set `stdout: 'ignore'` when that option is implemented +module.exports.stderr = (...args) => module.exports(...args).then(x => x.stderr); -var fs = __webpack_require__(22) -var MurmurHash3 = __webpack_require__(86) -var onExit = __webpack_require__(87) -var path = __webpack_require__(16) -var activeFiles = {} +module.exports.shell = (cmd, opts) => handleShell(module.exports, cmd, opts); -var invocations = 0 -function getTmpname (filename) { - return filename + '.' + - MurmurHash3(__filename) - .hash(String(process.pid)) - .hash(String(++invocations)) - .result() -} +module.exports.sync = (cmd, args, opts) => { + const parsed = handleArgs(cmd, args, opts); + const joinedCmd = joinCmd(cmd, args); -function cleanupOnExit (tmpfile) { - return function () { - try { - fs.unlinkSync(typeof tmpfile === 'function' ? tmpfile() : tmpfile) - } catch (_) {} - } -} + if (isStream(parsed.opts.input)) { + throw new TypeError('The `input` option cannot be a stream in sync mode'); + } -function writeFile (filename, data, options, callback) { - if (options instanceof Function) { - callback = options - options = null - } - if (!options) options = {} + const result = childProcess.spawnSync(parsed.cmd, parsed.args, parsed.opts); + result.code = result.status; - var Promise = options.Promise || global.Promise - var truename - var fd - var tmpfile - var removeOnExit = cleanupOnExit(() => tmpfile) - var absoluteName = path.resolve(filename) + if (result.error || result.status !== 0 || result.signal !== null) { + const err = makeError(result, { + joinedCmd, + parsed + }); - new Promise(function serializeSameFile (resolve) { - // make a queue if it doesn't already exist - if (!activeFiles[absoluteName]) activeFiles[absoluteName] = [] + if (!parsed.opts.reject) { + return err; + } - activeFiles[absoluteName].push(resolve) // add this job to the queue - if (activeFiles[absoluteName].length === 1) resolve() // kick off the first one - }).then(function getRealPath () { - return new Promise(function (resolve) { - fs.realpath(filename, function (_, realname) { - truename = realname || filename - tmpfile = getTmpname(truename) - resolve() - }) - }) - }).then(function stat () { - return new Promise(function stat (resolve) { - if (options.mode && options.chown) resolve() - else { - // Either mode or chown is not explicitly set - // Default behavior is to copy it from original file - fs.stat(truename, function (err, stats) { - if (err || !stats) resolve() - else { - options = Object.assign({}, options) + throw err; + } - if (!options.mode) { - options.mode = stats.mode - } - if (!options.chown && process.getuid) { - options.chown = { uid: stats.uid, gid: stats.gid } - } - resolve() - } - }) - } - }) - }).then(function thenWriteFile () { - return new Promise(function (resolve, reject) { - fs.open(tmpfile, 'w', options.mode, function (err, _fd) { - fd = _fd - if (err) reject(err) - else resolve() - }) - }) - }).then(function write () { - return new Promise(function (resolve, reject) { - if (Buffer.isBuffer(data)) { - fs.write(fd, data, 0, data.length, 0, function (err) { - if (err) reject(err) - else resolve() - }) - } else if (data != null) { - fs.write(fd, String(data), 0, String(options.encoding || 'utf8'), function (err) { - if (err) reject(err) - else resolve() - }) - } else resolve() - }) - }).then(function syncAndClose () { - if (options.fsync !== false) { - return new Promise(function (resolve, reject) { - fs.fsync(fd, function (err) { - if (err) reject(err) - else fs.close(fd, resolve) - }) - }) - } - }).then(function chown () { - if (options.chown) { - return new Promise(function (resolve, reject) { - fs.chown(tmpfile, options.chown.uid, options.chown.gid, function (err) { - if (err) reject(err) - else resolve() - }) - }) - } - }).then(function chmod () { - if (options.mode) { - return new Promise(function (resolve, reject) { - fs.chmod(tmpfile, options.mode, function (err) { - if (err) reject(err) - else resolve() - }) - }) - } - }).then(function rename () { - return new Promise(function (resolve, reject) { - fs.rename(tmpfile, truename, function (err) { - if (err) reject(err) - else resolve() - }) - }) - }).then(function success () { - removeOnExit() - callback() - }).catch(function fail (err) { - removeOnExit() - fs.unlink(tmpfile, function () { - callback(err) - }) - }).then(function checkQueue () { - activeFiles[absoluteName].shift() // remove the element added by serializeSameFile - if (activeFiles[absoluteName].length > 0) { - activeFiles[absoluteName][0]() // start next job if one is pending - } else delete activeFiles[absoluteName] - }) -} + return { + stdout: handleOutput(parsed.opts, result.stdout), + stderr: handleOutput(parsed.opts, result.stderr), + code: 0, + failed: false, + signal: null, + cmd: joinedCmd, + timedOut: false + }; +}; -function writeFileSync (filename, data, options) { - if (!options) options = {} - try { - filename = fs.realpathSync(filename) - } catch (ex) { - // it's ok, it'll happen on a not yet existing file - } - var tmpfile = getTmpname(filename) +module.exports.shellSync = (cmd, opts) => handleShell(module.exports.sync, cmd, opts); - try { - if (!options.mode || !options.chown) { - // Either mode or chown is not explicitly set - // Default behavior is to copy it from original file - try { - var stats = fs.statSync(filename) - options = Object.assign({}, options) - if (!options.mode) { - options.mode = stats.mode - } - if (!options.chown && process.getuid) { - options.chown = { uid: stats.uid, gid: stats.gid } - } - } catch (ex) { - // ignore stat errors - } - } - var removeOnExit = onExit(cleanupOnExit(tmpfile)) - var fd = fs.openSync(tmpfile, 'w', options.mode) - if (Buffer.isBuffer(data)) { - fs.writeSync(fd, data, 0, data.length, 0) - } else if (data != null) { - fs.writeSync(fd, String(data), 0, String(options.encoding || 'utf8')) - } - if (options.fsync !== false) { - fs.fsyncSync(fd) - } - fs.closeSync(fd) - if (options.chown) fs.chownSync(tmpfile, options.chown.uid, options.chown.gid) - if (options.mode) fs.chmodSync(tmpfile, options.mode) - fs.renameSync(tmpfile, filename) - removeOnExit() - } catch (err) { - removeOnExit() - try { fs.unlinkSync(tmpfile) } catch (e) {} - throw err - } -} +/***/ }), +/* 122 */ +/***/ (function(module, exports) { +module.exports = require("child_process"); /***/ }), -/* 86 */ +/* 123 */ /***/ (function(module, exports, __webpack_require__) { -/** - * @preserve - * JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013) - * - * @author Jens Taylor - * @see http://github.com/homebrewing/brauhaus-diff - * @author Gary Court - * @see http://github.com/garycourt/murmurhash-js - * @author Austin Appleby - * @see http://sites.google.com/site/murmurhash/ - */ -(function(){ - var cache; - - // Call this function without `new` to use the cached object (good for - // single-threaded environments), or with `new` to create a new object. - // - // @param {string} key A UTF-16 or ASCII string - // @param {number} seed An optional positive integer - // @return {object} A MurmurHash3 object for incremental hashing - function MurmurHash3(key, seed) { - var m = this instanceof MurmurHash3 ? this : cache; - m.reset(seed) - if (typeof key === 'string' && key.length > 0) { - m.hash(key); - } - - if (m !== this) { - return m; - } - }; +"use strict"; - // Incrementally add a string to this hash - // - // @param {string} key A UTF-16 or ASCII string - // @return {object} this - MurmurHash3.prototype.hash = function(key) { - var h1, k1, i, top, len; - len = key.length; - this.len += len; +const cp = __webpack_require__(122); +const parse = __webpack_require__(124); +const enoent = __webpack_require__(137); - k1 = this.k1; - i = 0; - switch (this.rem) { - case 0: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) : 0; - case 1: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 8 : 0; - case 2: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 16 : 0; - case 3: - k1 ^= len > i ? (key.charCodeAt(i) & 0xff) << 24 : 0; - k1 ^= len > i ? (key.charCodeAt(i++) & 0xff00) >> 8 : 0; - } +function spawn(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); - this.rem = (len + this.rem) & 3; // & 3 is same as % 4 - len -= this.rem; - if (len > 0) { - h1 = this.h1; - while (1) { - k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; - k1 = (k1 << 15) | (k1 >>> 17); - k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; + // Spawn the child process + const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); - h1 = (h1 * 5 + 0xe6546b64) & 0xffffffff; + // 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); - if (i >= len) { - break; - } + return spawned; +} - k1 = ((key.charCodeAt(i++) & 0xffff)) ^ - ((key.charCodeAt(i++) & 0xffff) << 8) ^ - ((key.charCodeAt(i++) & 0xffff) << 16); - top = key.charCodeAt(i++); - k1 ^= ((top & 0xff) << 24) ^ - ((top & 0xff00) >> 8); - } +function spawnSync(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); - k1 = 0; - switch (this.rem) { - case 3: k1 ^= (key.charCodeAt(i + 2) & 0xffff) << 16; - case 2: k1 ^= (key.charCodeAt(i + 1) & 0xffff) << 8; - case 1: k1 ^= (key.charCodeAt(i) & 0xffff); - } + // Spawn the child process + const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); - this.h1 = h1; - } + // 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); - this.k1 = k1; - return this; - }; + return result; +} - // Get the result of this hash - // - // @return {number} The 32-bit hash - MurmurHash3.prototype.result = function() { - var k1, h1; - - k1 = this.k1; - h1 = this.h1; +module.exports = spawn; +module.exports.spawn = spawn; +module.exports.sync = spawnSync; - if (k1 > 0) { - k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; - k1 = (k1 << 15) | (k1 >>> 17); - k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; - h1 ^= k1; - } +module.exports._parse = parse; +module.exports._enoent = enoent; - h1 ^= this.len; - h1 ^= h1 >>> 16; - h1 = (h1 * 0xca6b + (h1 & 0xffff) * 0x85eb0000) & 0xffffffff; - h1 ^= h1 >>> 13; - h1 = (h1 * 0xae35 + (h1 & 0xffff) * 0xc2b20000) & 0xffffffff; - h1 ^= h1 >>> 16; +/***/ }), +/* 124 */ +/***/ (function(module, exports, __webpack_require__) { - return h1 >>> 0; - }; +"use strict"; - // Reset the hash object for reuse - // - // @param {number} seed An optional positive integer - MurmurHash3.prototype.reset = function(seed) { - this.h1 = typeof seed === 'number' ? seed : 0; - this.rem = this.k1 = this.len = 0; - return this; - }; - // A cached object to use. This can be safely used if you're in a single- - // threaded environment, otherwise you need to create new hashes to use. - cache = new MurmurHash3(); +const path = __webpack_require__(16); +const niceTry = __webpack_require__(125); +const resolveCommand = __webpack_require__(126); +const escape = __webpack_require__(132); +const readShebang = __webpack_require__(133); +const semver = __webpack_require__(136); - if (true) { - module.exports = MurmurHash3; - } else {} -}()); +const isWin = process.platform === 'win32'; +const isExecutableRegExp = /\.(?:com|exe)$/i; +const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; +// `options.shell` is supported in Node ^4.8.0, ^5.7.0 and >= 6.0.0 +const supportsShellOption = niceTry(() => semver.satisfies(process.version, '^4.8.0 || ^5.7.0 || >= 6.0.0', true)) || false; -/***/ }), -/* 87 */ -/***/ (function(module, exports, __webpack_require__) { +function detectShebang(parsed) { + parsed.file = resolveCommand(parsed); -// 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__(30) -var signals = __webpack_require__(88) + const shebang = parsed.file && readShebang(parsed.file); -var EE = __webpack_require__(45) -/* istanbul ignore if */ -if (typeof EE !== 'function') { - EE = EE.EventEmitter -} + if (shebang) { + parsed.args.unshift(parsed.file); + parsed.command = shebang; -var emitter -if (process.__signal_exit_emitter__) { - emitter = process.__signal_exit_emitter__ -} else { - emitter = process.__signal_exit_emitter__ = new EE() - emitter.count = 0 - emitter.emitted = {} -} + return resolveCommand(parsed); + } -// Because this emitter is a global, we have to check to see if a -// previous version of this library failed to enable infinite listeners. -// I know what you're about to say. But literally everything about -// signal-exit is a compromise with evil. Get used to it. -if (!emitter.infinite) { - emitter.setMaxListeners(Infinity) - emitter.infinite = true + return parsed.file; } -module.exports = function (cb, opts) { - assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler') +function parseNonShell(parsed) { + if (!isWin) { + return parsed; + } - if (loaded === false) { - load() - } + // Detect & add support for shebangs + const commandFile = detectShebang(parsed); - var ev = 'exit' - if (opts && opts.alwaysLast) { - ev = 'afterexit' - } + // We don't need a shell if the command filename is an executable + const needsShell = !isExecutableRegExp.test(commandFile); - var remove = function () { - emitter.removeListener(ev, cb) - if (emitter.listeners('exit').length === 0 && - emitter.listeners('afterexit').length === 0) { - unload() + // 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); + + // 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); + + // Escape command & arguments + parsed.command = escape.command(parsed.command); + parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); + + const shellCommand = [parsed.command].concat(parsed.args).join(' '); + + 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 } - } - emitter.on(ev, cb) - return remove + return parsed; } -module.exports.unload = unload -function unload () { - if (!loaded) { - return - } - loaded = false +function parseShell(parsed) { + // If node supports the shell option, there's no need to mimic its behavior + if (supportsShellOption) { + return parsed; + } - signals.forEach(function (sig) { - try { - process.removeListener(sig, sigListeners[sig]) - } catch (er) {} - }) - process.emit = originalProcessEmit - process.reallyExit = originalProcessReallyExit - emitter.count -= 1 -} + // Mimic node shell option + // See https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335 + const shellCommand = [parsed.command].concat(parsed.args).join(' '); -function emit (event, code, signal) { - if (emitter.emitted[event]) { - return - } - emitter.emitted[event] = true - emitter.emit(event, code, signal) + if (isWin) { + parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe'; + parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped + } else { + if (typeof parsed.options.shell === 'string') { + parsed.command = parsed.options.shell; + } else if (process.platform === 'android') { + parsed.command = '/system/bin/sh'; + } else { + parsed.command = '/bin/sh'; + } + + parsed.args = ['-c', shellCommand]; + } + + return parsed; } -// { : , ... } -var sigListeners = {} -signals.forEach(function (sig) { - sigListeners[sig] = function listener () { - // If there are no other listeners, an exit is coming! - // Simplest way: remove us and then re-send the signal. - // We know that this will kill the process, so we can - // safely emit now. - var listeners = process.listeners(sig) - if (listeners.length === emitter.count) { - unload() - emit('exit', null, sig) - /* istanbul ignore next */ - emit('afterexit', null, sig) - /* istanbul ignore next */ - process.kill(process.pid, sig) +function parse(command, args, options) { + // Normalize arguments, similar to nodejs + if (args && !Array.isArray(args)) { + options = args; + args = null; } - } -}) -module.exports.signals = function () { - return signals + 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 ? parseShell(parsed) : parseNonShell(parsed); } -module.exports.load = load +module.exports = parse; -var loaded = false -function load () { - if (loaded) { - return - } - loaded = true +/***/ }), +/* 125 */ +/***/ (function(module, exports, __webpack_require__) { - // This is the number of onSignalExit's that are in play. - // It's important so that we can count the correct number of - // listeners on signals, and don't wait for the other one to - // handle it instead of us. - emitter.count += 1 +"use strict"; - signals = signals.filter(function (sig) { - try { - process.on(sig, sigListeners[sig]) - return true - } catch (er) { - return false - } - }) - process.emit = processEmit - process.reallyExit = processReallyExit -} +/** + * Tries to execute a function and discards any error that occurs. + * @param {Function} fn - Function that might or might not throw an error. + * @returns {?*} Return-value of the function when no error occurred. + */ +module.exports = function(fn) { + + try { return fn() } + catch (e) {} -var originalProcessReallyExit = process.reallyExit -function processReallyExit (code) { - process.exitCode = code || 0 - emit('exit', process.exitCode, null) - /* istanbul ignore next */ - emit('afterexit', process.exitCode, null) - /* istanbul ignore next */ - originalProcessReallyExit.call(process, process.exitCode) } -var originalProcessEmit = process.emit -function processEmit (ev, arg) { - if (ev === 'exit') { - if (arg !== undefined) { - process.exitCode = arg +/***/ }), +/* 126 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const path = __webpack_require__(16); +const which = __webpack_require__(127); +const pathKey = __webpack_require__(131)(); + +function resolveCommandAttempt(parsed, withoutPathExt) { + const cwd = process.cwd(); + const hasCustomCwd = parsed.options.cwd != null; + + // 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 (hasCustomCwd) { + try { + process.chdir(parsed.options.cwd); + } catch (err) { + /* Empty */ + } } - var ret = originalProcessEmit.apply(this, arguments) - emit('exit', process.exitCode, null) - /* istanbul ignore next */ - emit('afterexit', process.exitCode, null) - return ret - } else { - return originalProcessEmit.apply(this, arguments) - } -} + let resolved; -/***/ }), -/* 88 */ -/***/ (function(module, exports) { + try { + resolved = which.sync(parsed.command, { + path: (parsed.options.env || process.env)[pathKey], + pathExt: withoutPathExt ? path.delimiter : undefined, + }); + } catch (e) { + /* Empty */ + } finally { + process.chdir(cwd); + } -// This is not the set of all possible signals. -// -// It IS, however, the set of all signals that trigger -// an exit on either Linux or BSD systems. Linux is a -// superset of the signal names supported on BSD, and -// the unknown signals just fail to register, so we can -// catch that easily enough. -// -// Don't bother with SIGKILL. It's uncatchable, which -// means that we can't fire any callbacks anyway. -// -// If a user does happen to register a handler on a non- -// fatal signal like SIGWINCH or something, and then -// exit, it'll end up firing `process.emit('exit')`, so -// the handler will be fired anyway. -// -// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised -// artificially, inherently leave the process in a -// state from which it is not safe to try and enter JS -// listeners. -module.exports = [ - 'SIGABRT', - 'SIGALRM', - 'SIGHUP', - 'SIGINT', - 'SIGTERM' -] + // 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); + } -if (process.platform !== 'win32') { - module.exports.push( - 'SIGVTALRM', - 'SIGXCPU', - 'SIGXFSZ', - 'SIGUSR2', - 'SIGTRAP', - 'SIGSYS', - 'SIGQUIT', - 'SIGIOT' - // should detect profiler and enable/disable accordingly. - // see #21 - // 'SIGPROF' - ) + return resolved; } -if (process.platform === 'linux') { - module.exports.push( - 'SIGIO', - 'SIGPOLL', - 'SIGPWR', - 'SIGSTKFLT', - 'SIGUNUSED' - ) +function resolveCommand(parsed) { + return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); } +module.exports = resolveCommand; + /***/ }), -/* 89 */ +/* 127 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +module.exports = which +which.sync = whichSync -const isPlainObj = __webpack_require__(90); +var isWindows = process.platform === 'win32' || + process.env.OSTYPE === 'cygwin' || + process.env.OSTYPE === 'msys' -module.exports = (obj, opts) => { - if (!isPlainObj(obj)) { - throw new TypeError('Expected a plain object'); - } +var path = __webpack_require__(16) +var COLON = isWindows ? ';' : ':' +var isexe = __webpack_require__(128) - opts = opts || {}; +function getNotFoundError (cmd) { + var er = new Error('not found: ' + cmd) + er.code = 'ENOENT' - // DEPRECATED - if (typeof opts === 'function') { - throw new TypeError('Specify the compare function as an option instead'); - } + return er +} - const deep = opts.deep; - const seenInput = []; - const seenOutput = []; +function getPathInfo (cmd, opt) { + var colon = opt.colon || COLON + var pathEnv = opt.path || process.env.PATH || '' + var pathExt = [''] - const sortKeys = x => { - const seenIndex = seenInput.indexOf(x); + pathEnv = pathEnv.split(colon) - if (seenIndex !== -1) { - return seenOutput[seenIndex]; - } + var pathExtExe = '' + if (isWindows) { + pathEnv.unshift(process.cwd()) + pathExtExe = (opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM') + pathExt = pathExtExe.split(colon) - const ret = {}; - const keys = Object.keys(x).sort(opts.compare); - seenInput.push(x); - seenOutput.push(ret); + // Always test the cmd itself first. isexe will check to make sure + // it's found in the pathExt set. + if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') + pathExt.unshift('') + } - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const val = x[key]; + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + if (cmd.match(/\//) || isWindows && cmd.match(/\\/)) + pathEnv = [''] - if (deep && Array.isArray(val)) { - const retArr = []; + return { + env: pathEnv, + ext: pathExt, + extExe: pathExtExe + } +} - for (let j = 0; j < val.length; j++) { - retArr[j] = isPlainObj(val[j]) ? sortKeys(val[j]) : val[j]; - } +function which (cmd, opt, cb) { + if (typeof opt === 'function') { + cb = opt + opt = {} + } - ret[key] = retArr; - continue; - } + var info = getPathInfo(cmd, opt) + var pathEnv = info.env + var pathExt = info.ext + var pathExtExe = info.extExe + var found = [] - ret[key] = deep && isPlainObj(val) ? sortKeys(val) : val; - } + ;(function F (i, l) { + if (i === l) { + if (opt.all && found.length) + return cb(null, found) + else + return cb(getNotFoundError(cmd)) + } - return ret; - }; + var pathPart = pathEnv[i] + if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') + pathPart = pathPart.slice(1, -1) - return sortKeys(obj); -}; + var p = path.join(pathPart, cmd) + if (!pathPart && (/^\.[\\\/]/).test(cmd)) { + p = cmd.slice(0, 2) + p + } + ;(function E (ii, ll) { + if (ii === ll) return F(i + 1, l) + var ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, function (er, is) { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return cb(null, p + ext) + } + return E(ii + 1, ll) + }) + })(0, pathExt.length) + })(0, pathEnv.length) +} +function whichSync (cmd, opt) { + opt = opt || {} -/***/ }), -/* 90 */ -/***/ (function(module, exports, __webpack_require__) { + var info = getPathInfo(cmd, opt) + var pathEnv = info.env + var pathExt = info.ext + var pathExtExe = info.extExe + var found = [] -"use strict"; + for (var i = 0, l = pathEnv.length; i < l; i ++) { + var pathPart = pathEnv[i] + if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') + pathPart = pathPart.slice(1, -1) + + var p = path.join(pathPart, cmd) + if (!pathPart && /^\.[\\\/]/.test(cmd)) { + p = cmd.slice(0, 2) + p + } + for (var j = 0, ll = pathExt.length; j < ll; j ++) { + var cur = p + pathExt[j] + var is + try { + is = isexe.sync(cur, { pathExt: pathExtExe }) + if (is) { + if (opt.all) + found.push(cur) + else + return cur + } + } catch (ex) {} + } + } + + if (opt.all && found.length) + return found -var toString = Object.prototype.toString; + if (opt.nothrow) + return null -module.exports = function (x) { - var prototype; - return toString.call(x) === '[object Object]' && (prototype = Object.getPrototypeOf(x), prototype === null || prototype === Object.getPrototypeOf({})); -}; + throw getNotFoundError(cmd) +} /***/ }), -/* 91 */ +/* 128 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +var fs = __webpack_require__(23) +var core +if (process.platform === 'win32' || global.TESTING_WINDOWS) { + core = __webpack_require__(129) +} else { + core = __webpack_require__(130) +} -const fs = __webpack_require__(23); -const path = __webpack_require__(16); -const pify = __webpack_require__(92); +module.exports = isexe +isexe.sync = sync -const defaults = { - mode: 0o777 & (~process.umask()), - fs -}; +function isexe (path, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } -// https://github.com/nodejs/node/issues/8987 -// https://github.com/libuv/libuv/pull/1088 -const checkPath = pth => { - if (process.platform === 'win32') { - const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, '')); + if (!cb) { + if (typeof Promise !== 'function') { + throw new TypeError('callback not provided') + } - if (pathHasInvalidWinCharacters) { - const err = new Error(`Path contains invalid characters: ${pth}`); - err.code = 'EINVAL'; - throw err; - } - } -}; + return new Promise(function (resolve, reject) { + isexe(path, options || {}, function (er, is) { + if (er) { + reject(er) + } else { + resolve(is) + } + }) + }) + } -module.exports = (input, opts) => Promise.resolve().then(() => { - checkPath(input); - opts = Object.assign({}, defaults, opts); + 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) + }) +} - const mkdir = pify(opts.fs.mkdir); - const stat = pify(opts.fs.stat); +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 + } + } +} - const make = pth => { - return mkdir(pth, opts.mode) - .then(() => pth) - .catch(err => { - if (err.code === 'ENOENT') { - if (err.message.includes('null bytes') || path.dirname(pth) === pth) { - throw err; - } - return make(path.dirname(pth)).then(() => make(pth)); - } +/***/ }), +/* 129 */ +/***/ (function(module, exports, __webpack_require__) { - return stat(pth) - .then(stats => stats.isDirectory() ? pth : Promise.reject()) - .catch(() => { - throw err; - }); - }); - }; +module.exports = isexe +isexe.sync = sync - return make(path.resolve(input)); -}); +var fs = __webpack_require__(23) -module.exports.sync = (input, opts) => { - checkPath(input); - opts = Object.assign({}, defaults, opts); +function checkPathExt (path, options) { + var pathext = options.pathExt !== undefined ? + options.pathExt : process.env.PATHEXT - const make = pth => { - try { - opts.fs.mkdirSync(pth, opts.mode); - } catch (err) { - if (err.code === 'ENOENT') { - if (err.message.includes('null bytes') || path.dirname(pth) === pth) { - throw err; - } + if (!pathext) { + return true + } - make(path.dirname(pth)); - return make(pth); - } + 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 +} - try { - if (!opts.fs.statSync(pth).isDirectory()) { - throw new Error('The path is not a directory'); - } - } catch (_) { - throw err; - } - } +function checkStat (stat, path, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false + } + return checkPathExt(path, options) +} - return pth; - }; +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, path, options)) + }) +} - return make(path.resolve(input)); -}; +function sync (path, options) { + return checkStat(fs.statSync(path), path, options) +} /***/ }), -/* 92 */ +/* 130 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +module.exports = isexe +isexe.sync = sync +var fs = __webpack_require__(23) -const processFn = (fn, opts) => function () { - const P = opts.promiseModule; - const args = new Array(arguments.length); +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, options)) + }) +} - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } +function sync (path, options) { + return checkStat(fs.statSync(path), options) +} - return new P((resolve, reject) => { - if (opts.errorFirst) { - args.push(function (err, result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); +function checkStat (stat, options) { + return stat.isFile() && checkMode(stat, options) +} - for (let i = 1; i < arguments.length; i++) { - results[i - 1] = arguments[i]; - } +function checkMode (stat, options) { + var mod = stat.mode + var uid = stat.uid + var gid = stat.gid - if (err) { - results.unshift(err); - reject(results); - } else { - resolve(results); - } - } else if (err) { - reject(err); - } else { - resolve(result); - } - }); - } else { - args.push(function (result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); + var myUid = options.uid !== undefined ? + options.uid : process.getuid && process.getuid() + var myGid = options.gid !== undefined ? + options.gid : process.getgid && process.getgid() - for (let i = 0; i < arguments.length; i++) { - results[i] = arguments[i]; - } + var u = parseInt('100', 8) + var g = parseInt('010', 8) + var o = parseInt('001', 8) + var ug = u | g - resolve(results); - } else { - resolve(result); - } - }); - } + var ret = (mod & o) || + (mod & g) && gid === myGid || + (mod & u) && uid === myUid || + (mod & ug) && myUid === 0 - fn.apply(this, args); - }); -}; + return ret +} -module.exports = (obj, opts) => { - opts = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, opts); - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return opts.include ? opts.include.some(match) : !opts.exclude.some(match); - }; +/***/ }), +/* 131 */ +/***/ (function(module, exports, __webpack_require__) { - let ret; - if (typeof obj === 'function') { - ret = function () { - if (opts.excludeMain) { - return obj.apply(this, arguments); - } +"use strict"; - return processFn(obj, opts).apply(this, arguments); - }; - } else { - ret = Object.create(Object.getPrototypeOf(obj)); - } +module.exports = opts => { + opts = opts || {}; - for (const key in obj) { // eslint-disable-line guard-for-in - const x = obj[key]; - ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; + const env = opts.env || process.env; + const platform = opts.platform || process.platform; + + if (platform !== 'win32') { + return 'PATH'; } - return ret; + return Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; }; /***/ }), -/* 93 */ +/* 132 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const processFn = (fn, opts) => function () { - const P = opts.promiseModule; - const args = new Array(arguments.length); - - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } +// See http://www.robvanderwoude.com/escapechars.php +const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; - return new P((resolve, reject) => { - if (opts.errorFirst) { - args.push(function (err, result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); +function escapeCommand(arg) { + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); - for (let i = 1; i < arguments.length; i++) { - results[i - 1] = arguments[i]; - } + return arg; +} - if (err) { - results.unshift(err); - reject(results); - } else { - resolve(results); - } - } else if (err) { - reject(err); - } else { - resolve(result); - } - }); - } else { - args.push(function (result) { - if (opts.multiArgs) { - const results = new Array(arguments.length - 1); +function escapeArgument(arg, doubleEscapeMetaChars) { + // Convert to string + arg = `${arg}`; - for (let i = 0; i < arguments.length; i++) { - results[i] = arguments[i]; - } + // Algorithm below is based on https://qntm.org/cmd - resolve(results); - } else { - resolve(result); - } - }); - } + // Sequence of backslashes followed by a double quote: + // double up all the backslashes and escape the double quote + arg = arg.replace(/(\\*)"/g, '$1$1\\"'); - fn.apply(this, args); - }); -}; + // 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'); -module.exports = (obj, opts) => { - opts = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, opts); + // All other backslashes occur literally - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return opts.include ? opts.include.some(match) : !opts.exclude.some(match); - }; + // Quote the whole thing: + arg = `"${arg}"`; - let ret; - if (typeof obj === 'function') { - ret = function () { - if (opts.excludeMain) { - return obj.apply(this, arguments); - } + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); - return processFn(obj, opts).apply(this, arguments); - }; - } else { - ret = Object.create(Object.getPrototypeOf(obj)); - } + // Double escape meta chars if necessary + if (doubleEscapeMetaChars) { + arg = arg.replace(metaCharsRegExp, '^$1'); + } - for (const key in obj) { // eslint-disable-line guard-for-in - const x = obj[key]; - ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; - } + return arg; +} - return ret; -}; +module.exports.command = escapeCommand; +module.exports.argument = escapeArgument; /***/ }), -/* 94 */ +/* 133 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -// detect either spaces or tabs but not both to properly handle tabs -// for indentation and spaces for alignment -const INDENT_RE = /^(?:( )+|\t+)/; +const fs = __webpack_require__(23); +const shebangCommand = __webpack_require__(134); -function getMostUsed(indents) { - let result = 0; - let maxUsed = 0; - let maxWeight = 0; +function readShebang(command) { + // Read the first 150 bytes from the file + const size = 150; + let buffer; - for (const entry of indents) { - // TODO: use destructuring when targeting Node.js 6 - const key = entry[0]; - const val = entry[1]; + if (Buffer.alloc) { + // Node.js v4.5+ / v5.10+ + buffer = Buffer.alloc(size); + } else { + // Old Node.js API + buffer = new Buffer(size); + buffer.fill(0); // zero-fill + } - const u = val[0]; - const w = val[1]; + let fd; - if (u > maxUsed || (u === maxUsed && w > maxWeight)) { - maxUsed = u; - maxWeight = w; - result = Number(key); - } - } + try { + fd = fs.openSync(command, 'r'); + fs.readSync(fd, buffer, 0, size, 0); + fs.closeSync(fd); + } catch (e) { /* Empty */ } - return result; + // Attempt to extract shebang (null is returned if not a shebang) + return shebangCommand(buffer.toString()); } -module.exports = str => { - if (typeof str !== 'string') { - throw new TypeError('Expected a string'); - } - - // used to see if tabs or spaces are the most used - let tabs = 0; - let spaces = 0; - - // remember the size of previous line's indentation - let prev = 0; - - // remember how many indents/unindents as occurred for a given size - // and how much lines follow a given indentation - // - // indents = { - // 3: [1, 0], - // 4: [1, 5], - // 5: [1, 0], - // 12: [1, 0], - // } - const indents = new Map(); - - // pointer to the array of last used indent - let current; - - // whether the last action was an indent (opposed to an unindent) - let isIndent; - - for (const line of str.split(/\n/g)) { - if (!line) { - // ignore empty lines - continue; - } - - let indent; - const matches = line.match(INDENT_RE); - - if (matches) { - indent = matches[0].length; - - if (matches[1]) { - spaces++; - } else { - tabs++; - } - } else { - indent = 0; - } - - const diff = indent - prev; - prev = indent; - - if (diff) { - // an indent or unindent has been detected - - isIndent = diff > 0; - - current = indents.get(isIndent ? diff : -diff); - - if (current) { - current[0]++; - } else { - current = [1, 0]; - indents.set(diff, current); - } - } else if (current) { - // if the last action was an indent, increment the weight - current[1] += Number(isIndent); - } - } +module.exports = readShebang; - const amount = getMostUsed(indents); - let type; - let indent; - if (!amount) { - type = null; - indent = ''; - } else if (spaces >= tabs) { - type = 'space'; - indent = ' '.repeat(amount); - } else { - type = 'tab'; - indent = '\t'.repeat(amount); +/***/ }), +/* 134 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var shebangRegex = __webpack_require__(135); + +module.exports = function (str) { + var match = str.match(shebangRegex); + + if (!match) { + return null; } - return { - amount, - type, - indent - }; + var arr = match[0].replace(/#! ?/, '').split(' '); + var bin = arr[0].split('/').pop(); + var arg = arr[1]; + + return (bin === 'env' ? + arg : + bin + (arg ? ' ' + arg : '') + ); }; /***/ }), -/* 95 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/* 135 */ +/***/ (function(module, exports, __webpack_require__) { "use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "installInDir", function() { return installInDir; }); -/* 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__(96); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 = /^#!.*/; -/** - * Install all dependencies in the given directory - */ -async function installInDir(directory, extraArgs = []) { - const options = ['install', '--non-interactive', ...extraArgs]; // We pass the mutex flag to ensure only one instance of yarn runs at any - // given time (e.g. to avoid conflicts). - await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', options, { - cwd: directory - }); -} -/** - * Run script in the given directory - */ +/***/ }), +/* 136 */ +/***/ (function(module, exports) { -async function runScriptInPackage(script, args, pkg) { - const execOpts = { - cwd: pkg.path - }; - await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['run', script, ...args], execOpts); -} -/** - * Run script in the given directory - */ +exports = module.exports = SemVer; -function runScriptInPackageStreaming(script, args, pkg) { - const execOpts = { - cwd: pkg.path - }; - return Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawnStreaming"])('yarn', ['run', script, ...args], execOpts, { - prefix: pkg.name - }); -} -async function yarnWorkspacesInfo(directory) { - const workspacesInfo = await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['workspaces', 'info', '--json'], { - cwd: directory, - stdio: 'pipe' - }); - const stdout = JSON.parse(workspacesInfo.stdout); - return JSON.parse(stdout.data); -} +// The debug function is excluded entirely from the minified version. +/* nomin */ var debug; +/* nomin */ if (typeof process === 'object' && + /* nomin */ process.env && + /* nomin */ process.env.NODE_DEBUG && + /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) + /* nomin */ debug = function() { + /* nomin */ var args = Array.prototype.slice.call(arguments, 0); + /* nomin */ args.unshift('SEMVER'); + /* nomin */ console.log.apply(console, args); + /* nomin */ }; +/* nomin */ else + /* nomin */ debug = function() {}; -/***/ }), -/* 96 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0'; -"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 chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(97); -/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(125); -/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(126); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } +var MAX_LENGTH = 256; +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; -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; } +// Max safe segment length for coercion. +var MAX_SAFE_COMPONENT_LENGTH = 16; -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +// The actual regexps go on exports.re +var re = exports.re = []; +var src = exports.src = []; +var R = 0; +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. +var NUMERICIDENTIFIER = R++; +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; +var NUMERICIDENTIFIERLOOSE = R++; +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; -function generateColors() { - const colorWheel = [chalk__WEBPACK_IMPORTED_MODULE_0___default.a.cyan, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.magenta, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.blue, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.yellow, chalk__WEBPACK_IMPORTED_MODULE_0___default.a.green]; - const count = colorWheel.length; - let children = 0; - return () => colorWheel[children++ % count]; -} +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. -function spawn(command, args, opts) { - return execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({ - stdio: 'inherit' - }, opts)); -} -const nextColor = generateColors(); -function spawnStreaming(command, args, opts, { - prefix -}) { - const spawned = execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({ - stdio: ['ignore', 'pipe', 'pipe'] - }, opts)); - const color = nextColor(); - const prefixedStdout = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ - tag: `${color.bold(prefix)}:` - }); - const prefixedStderr = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ - mergeMultiline: true, - tag: `${log_symbols__WEBPACK_IMPORTED_MODULE_2___default.a.error} ${color.bold(prefix)}:` - }); - spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); - spawned.stderr.pipe(prefixedStderr).pipe(process.stderr); - return spawned; -} +var NONNUMERICIDENTIFIER = R++; +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; -/***/ }), -/* 97 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; +// ## Main Version +// Three dot-separated numeric identifiers. -const path = __webpack_require__(16); -const childProcess = __webpack_require__(98); -const crossSpawn = __webpack_require__(99); -const stripEof = __webpack_require__(114); -const npmRunPath = __webpack_require__(115); -const isStream = __webpack_require__(117); -const _getStream = __webpack_require__(118); -const pFinally = __webpack_require__(122); -const onExit = __webpack_require__(87); -const errname = __webpack_require__(123); -const stdio = __webpack_require__(124); +var MAINVERSION = R++; +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')'; -const TEN_MEGABYTES = 1000 * 1000 * 10; +var MAINVERSIONLOOSE = R++; +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; -function handleArgs(cmd, args, opts) { - let parsed; +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. - opts = Object.assign({ - extendEnv: true, - env: {} - }, opts); +var PRERELEASEIDENTIFIER = R++; +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; - if (opts.extendEnv) { - opts.env = Object.assign({}, process.env, opts.env); - } +var PRERELEASEIDENTIFIERLOOSE = R++; +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; - if (opts.__winShell === true) { - delete opts.__winShell; - parsed = { - command: cmd, - args, - options: opts, - file: cmd, - original: { - cmd, - args - } - }; - } else { - parsed = crossSpawn._parse(cmd, args, opts); - } - opts = Object.assign({ - maxBuffer: TEN_MEGABYTES, - buffer: true, - stripEof: true, - preferLocal: true, - localDir: parsed.options.cwd || process.cwd(), - encoding: 'utf8', - reject: true, - cleanup: true - }, parsed.options); +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. - opts.stdio = stdio(opts); +var PRERELEASE = R++; +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; - if (opts.preferLocal) { - opts.env = npmRunPath.env(Object.assign({}, opts, {cwd: opts.localDir})); - } +var PRERELEASELOOSE = R++; +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; - if (opts.detached) { - // #115 - opts.cleanup = false; - } +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. - if (process.platform === 'win32' && path.basename(parsed.command) === 'cmd.exe') { - // #116 - parsed.args.unshift('/q'); - } +var BUILDIDENTIFIER = R++; +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; - return { - cmd: parsed.command, - args: parsed.args, - opts, - parsed - }; -} +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. -function handleInput(spawned, input) { - if (input === null || input === undefined) { - return; - } +var BUILD = R++; +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; - if (isStream(input)) { - input.pipe(spawned.stdin); - } else { - spawned.stdin.end(input); - } -} -function handleOutput(opts, val) { - if (val && opts.stripEof) { - val = stripEof(val); - } +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. - return val; -} +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. -function handleShell(fn, cmd, opts) { - let file = '/bin/sh'; - let args = ['-c', cmd]; +var FULL = R++; +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?'; - opts = Object.assign({}, opts); +src[FULL] = '^' + FULLPLAIN + '$'; - if (process.platform === 'win32') { - opts.__winShell = true; - file = process.env.comspec || 'cmd.exe'; - args = ['/s', '/c', `"${cmd}"`]; - opts.windowsVerbatimArguments = true; - } +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?'; - if (opts.shell) { - file = opts.shell; - delete opts.shell; - } +var LOOSE = R++; +src[LOOSE] = '^' + LOOSEPLAIN + '$'; - return fn(file, args, opts); -} +var GTLT = R++; +src[GTLT] = '((?:<|>)?=?)'; -function getStream(process, stream, {encoding, buffer, maxBuffer}) { - if (!process[stream]) { - return null; - } +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++; +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; +var XRANGEIDENTIFIER = R++; +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; - let ret; +var XRANGEPLAIN = R++; +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?'; - if (!buffer) { - // TODO: Use `ret = util.promisify(stream.finished)(process[stream]);` when targeting Node.js 10 - ret = new Promise((resolve, reject) => { - process[stream] - .once('end', resolve) - .once('error', reject); - }); - } else if (encoding) { - ret = _getStream(process[stream], { - encoding, - maxBuffer - }); - } else { - ret = _getStream.buffer(process[stream], {maxBuffer}); - } +var XRANGEPLAINLOOSE = R++; +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?'; - return ret.catch(err => { - err.stream = stream; - err.message = `${stream} ${err.message}`; - throw err; - }); -} +var XRANGE = R++; +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; +var XRANGELOOSE = R++; +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; -function makeError(result, options) { - const {stdout, stderr} = result; +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +var COERCE = R++; +src[COERCE] = '(?:^|[^\\d])' + + '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:$|[^\\d])'; - let err = result.error; - const {code, signal} = result; +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++; +src[LONETILDE] = '(?:~>?)'; - const {parsed, joinedCmd} = options; - const timedOut = options.timedOut || false; +var TILDETRIM = R++; +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); +var tildeTrimReplace = '$1~'; - if (!err) { - let output = ''; +var TILDE = R++; +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; +var TILDELOOSE = R++; +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; - if (Array.isArray(parsed.opts.stdio)) { - if (parsed.opts.stdio[2] !== 'inherit') { - output += output.length > 0 ? stderr : `\n${stderr}`; - } +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++; +src[LONECARET] = '(?:\\^)'; - if (parsed.opts.stdio[1] !== 'inherit') { - output += `\n${stdout}`; - } - } else if (parsed.opts.stdio !== 'inherit') { - output = `\n${stderr}${stdout}`; - } +var CARETTRIM = R++; +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); +var caretTrimReplace = '$1^'; - err = new Error(`Command failed: ${joinedCmd}${output}`); - err.code = code < 0 ? errname(code) : code; - } +var CARET = R++; +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; +var CARETLOOSE = R++; +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; - err.stdout = stdout; - err.stderr = stderr; - err.failed = true; - err.signal = signal || null; - err.cmd = joinedCmd; - err.timedOut = timedOut; +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++; +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; +var COMPARATOR = R++; +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; - return err; -} -function joinCmd(cmd, args) { - let joinedCmd = cmd; +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++; +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; - if (Array.isArray(args) && args.length > 0) { - joinedCmd += ' ' + args.join(' '); - } +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); +var comparatorTrimReplace = '$1$2$3'; - return joinedCmd; + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++; +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$'; + +var HYPHENRANGELOOSE = R++; +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$'; + +// Star ranges basically just allow anything at all. +var STAR = R++; +src[STAR] = '(<|>)?=?\\s*\\*'; + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]); + if (!re[i]) + re[i] = new RegExp(src[i]); } -module.exports = (cmd, args, opts) => { - const parsed = handleArgs(cmd, args, opts); - const {encoding, buffer, maxBuffer} = parsed.opts; - const joinedCmd = joinCmd(cmd, args); +exports.parse = parse; +function parse(version, loose) { + if (version instanceof SemVer) + return version; + + if (typeof version !== 'string') + return null; - let spawned; - try { - spawned = childProcess.spawn(parsed.cmd, parsed.args, parsed.opts); - } catch (err) { - return Promise.reject(err); - } + if (version.length > MAX_LENGTH) + return null; - let removeExitHandler; - if (parsed.opts.cleanup) { - removeExitHandler = onExit(() => { - spawned.kill(); - }); - } + var r = loose ? re[LOOSE] : re[FULL]; + if (!r.test(version)) + return null; - let timeoutId = null; - let timedOut = false; + try { + return new SemVer(version, loose); + } catch (er) { + return null; + } +} - const cleanup = () => { - if (timeoutId) { - clearTimeout(timeoutId); - timeoutId = null; - } +exports.valid = valid; +function valid(version, loose) { + var v = parse(version, loose); + return v ? v.version : null; +} - if (removeExitHandler) { - removeExitHandler(); - } - }; - if (parsed.opts.timeout > 0) { - timeoutId = setTimeout(() => { - timeoutId = null; - timedOut = true; - spawned.kill(parsed.opts.killSignal); - }, parsed.opts.timeout); - } +exports.clean = clean; +function clean(version, loose) { + var s = parse(version.trim().replace(/^[=v]+/, ''), loose); + return s ? s.version : null; +} - const processDone = new Promise(resolve => { - spawned.on('exit', (code, signal) => { - cleanup(); - resolve({code, signal}); - }); +exports.SemVer = SemVer; - spawned.on('error', err => { - cleanup(); - resolve({error: err}); - }); +function SemVer(version, loose) { + if (version instanceof SemVer) { + if (version.loose === loose) + return version; + else + version = version.version; + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version); + } - if (spawned.stdin) { - spawned.stdin.on('error', err => { - cleanup(); - resolve({error: err}); - }); - } - }); + if (version.length > MAX_LENGTH) + throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - function destroy() { - if (spawned.stdout) { - spawned.stdout.destroy(); - } + if (!(this instanceof SemVer)) + return new SemVer(version, loose); - if (spawned.stderr) { - spawned.stderr.destroy(); - } - } + debug('SemVer', version, loose); + this.loose = loose; + var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); - const handlePromise = () => pFinally(Promise.all([ - processDone, - getStream(spawned, 'stdout', {encoding, buffer, maxBuffer}), - getStream(spawned, 'stderr', {encoding, buffer, maxBuffer}) - ]).then(arr => { - const result = arr[0]; - result.stdout = arr[1]; - result.stderr = arr[2]; + if (!m) + throw new TypeError('Invalid Version: ' + version); - if (result.error || result.code !== 0 || result.signal !== null) { - const err = makeError(result, { - joinedCmd, - parsed, - timedOut - }); + this.raw = version; - // TODO: missing some timeout logic for killed - // https://github.com/nodejs/node/blob/master/lib/child_process.js#L203 - // err.killed = spawned.killed || killed; - err.killed = err.killed || spawned.killed; + // these are actually numbers + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; - if (!parsed.opts.reject) { - return err; - } + if (this.major > MAX_SAFE_INTEGER || this.major < 0) + throw new TypeError('Invalid major version') - throw err; - } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) + throw new TypeError('Invalid minor version') - return { - stdout: handleOutput(parsed.opts, result.stdout), - stderr: handleOutput(parsed.opts, result.stderr), - code: 0, - failed: false, - killed: false, - signal: null, - cmd: joinedCmd, - timedOut: false - }; - }), destroy); + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) + throw new TypeError('Invalid patch version') - crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); + // numberify any prerelease numeric ids + if (!m[4]) + this.prerelease = []; + else + this.prerelease = m[4].split('.').map(function(id) { + if (/^[0-9]+$/.test(id)) { + var num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) + return num; + } + return id; + }); - handleInput(spawned, parsed.opts.input); + this.build = m[5] ? m[5].split('.') : []; + this.format(); +} - spawned.then = (onfulfilled, onrejected) => handlePromise().then(onfulfilled, onrejected); - spawned.catch = onrejected => handlePromise().catch(onrejected); +SemVer.prototype.format = function() { + this.version = this.major + '.' + this.minor + '.' + this.patch; + if (this.prerelease.length) + this.version += '-' + this.prerelease.join('.'); + return this.version; +}; - return spawned; +SemVer.prototype.toString = function() { + return this.version; }; -// TODO: set `stderr: 'ignore'` when that option is implemented -module.exports.stdout = (...args) => module.exports(...args).then(x => x.stdout); +SemVer.prototype.compare = function(other) { + debug('SemVer.compare', this.version, this.loose, other); + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); -// TODO: set `stdout: 'ignore'` when that option is implemented -module.exports.stderr = (...args) => module.exports(...args).then(x => x.stderr); + return this.compareMain(other) || this.comparePre(other); +}; -module.exports.shell = (cmd, opts) => handleShell(module.exports, cmd, opts); +SemVer.prototype.compareMain = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); -module.exports.sync = (cmd, args, opts) => { - const parsed = handleArgs(cmd, args, opts); - const joinedCmd = joinCmd(cmd, args); + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch); +}; - if (isStream(parsed.opts.input)) { - throw new TypeError('The `input` option cannot be a stream in sync mode'); - } +SemVer.prototype.comparePre = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); - const result = childProcess.spawnSync(parsed.cmd, parsed.args, parsed.opts); - result.code = result.status; + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) + return -1; + else if (!this.prerelease.length && other.prerelease.length) + return 1; + else if (!this.prerelease.length && !other.prerelease.length) + return 0; - if (result.error || result.status !== 0 || result.signal !== null) { - const err = makeError(result, { - joinedCmd, - parsed - }); + var i = 0; + do { + var a = this.prerelease[i]; + var b = other.prerelease[i]; + debug('prerelease compare', i, a, b); + if (a === undefined && b === undefined) + return 0; + else if (b === undefined) + return 1; + else if (a === undefined) + return -1; + else if (a === b) + continue; + else + return compareIdentifiers(a, b); + } while (++i); +}; - if (!parsed.opts.reject) { - return err; - } +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function(release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc('pre', identifier); + break; + case 'preminor': + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc('pre', identifier); + break; + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0; + this.inc('patch', identifier); + this.inc('pre', identifier); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) + this.inc('patch', identifier); + this.inc('pre', identifier); + break; - throw err; - } + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) + this.major++; + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) + this.minor++; + this.patch = 0; + this.prerelease = []; + break; + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) + this.patch++; + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) + this.prerelease = [0]; + else { + var i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) // didn't increment anything + this.prerelease.push(0); + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) + this.prerelease = [identifier, 0]; + } else + this.prerelease = [identifier, 0]; + } + break; - return { - stdout: handleOutput(parsed.opts, result.stdout), - stderr: handleOutput(parsed.opts, result.stderr), - code: 0, - failed: false, - signal: null, - cmd: joinedCmd, - timedOut: false - }; + default: + throw new Error('invalid increment argument: ' + release); + } + this.format(); + this.raw = this.version; + return this; }; -module.exports.shellSync = (cmd, opts) => handleShell(module.exports.sync, cmd, opts); - - -/***/ }), -/* 98 */ -/***/ (function(module, exports) { +exports.inc = inc; +function inc(version, release, loose, identifier) { + if (typeof(loose) === 'string') { + identifier = loose; + loose = undefined; + } -module.exports = require("child_process"); + try { + return new SemVer(version, loose).inc(release, identifier).version; + } catch (er) { + return null; + } +} -/***/ }), -/* 99 */ -/***/ (function(module, exports, __webpack_require__) { +exports.diff = diff; +function diff(version1, version2) { + if (eq(version1, version2)) { + return null; + } else { + var v1 = parse(version1); + var v2 = parse(version2); + if (v1.prerelease.length || v2.prerelease.length) { + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return 'pre'+key; + } + } + } + return 'prerelease'; + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return key; + } + } + } + } +} -"use strict"; +exports.compareIdentifiers = compareIdentifiers; +var numeric = /^[0-9]+$/; +function compareIdentifiers(a, b) { + var anum = numeric.test(a); + var bnum = numeric.test(b); -const cp = __webpack_require__(98); -const parse = __webpack_require__(100); -const enoent = __webpack_require__(113); + if (anum && bnum) { + a = +a; + b = +b; + } -function spawn(command, args, options) { - // Parse the arguments - const parsed = parse(command, args, options); + return (anum && !bnum) ? -1 : + (bnum && !anum) ? 1 : + a < b ? -1 : + a > b ? 1 : + 0; +} - // Spawn the child process - const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); +exports.rcompareIdentifiers = rcompareIdentifiers; +function rcompareIdentifiers(a, b) { + return compareIdentifiers(b, a); +} - // 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); +exports.major = major; +function major(a, loose) { + return new SemVer(a, loose).major; +} - return spawned; +exports.minor = minor; +function minor(a, loose) { + return new SemVer(a, loose).minor; } -function spawnSync(command, args, options) { - // Parse the arguments - const parsed = parse(command, args, options); +exports.patch = patch; +function patch(a, loose) { + return new SemVer(a, loose).patch; +} - // Spawn the child process - const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); +exports.compare = compare; +function compare(a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)); +} - // 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); +exports.compareLoose = compareLoose; +function compareLoose(a, b) { + return compare(a, b, true); +} - return result; +exports.rcompare = rcompare; +function rcompare(a, b, loose) { + return compare(b, a, loose); } -module.exports = spawn; -module.exports.spawn = spawn; -module.exports.sync = spawnSync; +exports.sort = sort; +function sort(list, loose) { + return list.sort(function(a, b) { + return exports.compare(a, b, loose); + }); +} -module.exports._parse = parse; -module.exports._enoent = enoent; +exports.rsort = rsort; +function rsort(list, loose) { + return list.sort(function(a, b) { + return exports.rcompare(a, b, loose); + }); +} +exports.gt = gt; +function gt(a, b, loose) { + return compare(a, b, loose) > 0; +} -/***/ }), -/* 100 */ -/***/ (function(module, exports, __webpack_require__) { +exports.lt = lt; +function lt(a, b, loose) { + return compare(a, b, loose) < 0; +} -"use strict"; +exports.eq = eq; +function eq(a, b, loose) { + return compare(a, b, loose) === 0; +} +exports.neq = neq; +function neq(a, b, loose) { + return compare(a, b, loose) !== 0; +} -const path = __webpack_require__(16); -const niceTry = __webpack_require__(101); -const resolveCommand = __webpack_require__(102); -const escape = __webpack_require__(108); -const readShebang = __webpack_require__(109); -const semver = __webpack_require__(112); +exports.gte = gte; +function gte(a, b, loose) { + return compare(a, b, loose) >= 0; +} -const isWin = process.platform === 'win32'; -const isExecutableRegExp = /\.(?:com|exe)$/i; -const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; +exports.lte = lte; +function lte(a, b, loose) { + return compare(a, b, loose) <= 0; +} -// `options.shell` is supported in Node ^4.8.0, ^5.7.0 and >= 6.0.0 -const supportsShellOption = niceTry(() => semver.satisfies(process.version, '^4.8.0 || ^5.7.0 || >= 6.0.0', true)) || false; +exports.cmp = cmp; +function cmp(a, op, b, loose) { + var ret; + switch (op) { + case '===': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a === b; + break; + case '!==': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a !== b; + break; + case '': case '=': case '==': ret = eq(a, b, loose); break; + case '!=': ret = neq(a, b, loose); break; + case '>': ret = gt(a, b, loose); break; + case '>=': ret = gte(a, b, loose); break; + case '<': ret = lt(a, b, loose); break; + case '<=': ret = lte(a, b, loose); break; + default: throw new TypeError('Invalid operator: ' + op); + } + return ret; +} -function detectShebang(parsed) { - parsed.file = resolveCommand(parsed); +exports.Comparator = Comparator; +function Comparator(comp, loose) { + if (comp instanceof Comparator) { + if (comp.loose === loose) + return comp; + else + comp = comp.value; + } - const shebang = parsed.file && readShebang(parsed.file); + if (!(this instanceof Comparator)) + return new Comparator(comp, loose); - if (shebang) { - parsed.args.unshift(parsed.file); - parsed.command = shebang; + debug('comparator', comp, loose); + this.loose = loose; + this.parse(comp); - return resolveCommand(parsed); - } + if (this.semver === ANY) + this.value = ''; + else + this.value = this.operator + this.semver.version; - return parsed.file; + debug('comp', this); } -function parseNonShell(parsed) { - if (!isWin) { - return parsed; - } - - // Detect & add support for shebangs - const commandFile = detectShebang(parsed); +var ANY = {}; +Comparator.prototype.parse = function(comp) { + var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var m = comp.match(r); - // We don't need a shell if the command filename is an executable - const needsShell = !isExecutableRegExp.test(commandFile); + if (!m) + throw new TypeError('Invalid comparator: ' + comp); - // 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); + this.operator = m[1]; + if (this.operator === '=') + this.operator = ''; - // 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); + // if it literally is just '>' or '' then allow anything. + if (!m[2]) + this.semver = ANY; + else + this.semver = new SemVer(m[2], this.loose); +}; - // Escape command & arguments - parsed.command = escape.command(parsed.command); - parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); +Comparator.prototype.toString = function() { + return this.value; +}; - const shellCommand = [parsed.command].concat(parsed.args).join(' '); +Comparator.prototype.test = function(version) { + debug('Comparator.test', version, this.loose); - 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 - } + if (this.semver === ANY) + return true; - return parsed; -} + if (typeof version === 'string') + version = new SemVer(version, this.loose); -function parseShell(parsed) { - // If node supports the shell option, there's no need to mimic its behavior - if (supportsShellOption) { - return parsed; - } + return cmp(version, this.operator, this.semver, this.loose); +}; - // Mimic node shell option - // See https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335 - const shellCommand = [parsed.command].concat(parsed.args).join(' '); +Comparator.prototype.intersects = function(comp, loose) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required'); + } - if (isWin) { - parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe'; - parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; - parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped - } else { - if (typeof parsed.options.shell === 'string') { - parsed.command = parsed.options.shell; - } else if (process.platform === 'android') { - parsed.command = '/system/bin/sh'; - } else { - parsed.command = '/bin/sh'; - } + var rangeTmp; - parsed.args = ['-c', shellCommand]; - } + if (this.operator === '') { + rangeTmp = new Range(comp.value, loose); + return satisfies(this.value, rangeTmp, loose); + } else if (comp.operator === '') { + rangeTmp = new Range(this.value, loose); + return satisfies(comp.semver, rangeTmp, loose); + } - return parsed; -} + var sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>'); + var sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<'); + var sameSemVer = this.semver.version === comp.semver.version; + var differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<='); + var oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, loose) && + ((this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<')); + var oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, loose) && + ((this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>')); -function parse(command, args, options) { - // Normalize arguments, similar to nodejs - if (args && !Array.isArray(args)) { - options = args; - args = null; - } + return sameDirectionIncreasing || sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; +}; - 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, - }, - }; +exports.Range = Range; +function Range(range, loose) { + if (range instanceof Range) { + if (range.loose === loose) { + return range; + } else { + return new Range(range.raw, loose); + } + } - // Delegate further parsing to shell or non-shell - return options.shell ? parseShell(parsed) : parseNonShell(parsed); -} + if (range instanceof Comparator) { + return new Range(range.value, loose); + } -module.exports = parse; + if (!(this instanceof Range)) + return new Range(range, loose); + this.loose = loose; -/***/ }), -/* 101 */ -/***/ (function(module, exports, __webpack_require__) { + // First, split based on boolean or || + this.raw = range; + this.set = range.split(/\s*\|\|\s*/).map(function(range) { + return this.parseRange(range.trim()); + }, this).filter(function(c) { + // throw out any that are not relevant for whatever reason + return c.length; + }); -"use strict"; + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range); + } + this.format(); +} -/** - * Tries to execute a function and discards any error that occurs. - * @param {Function} fn - Function that might or might not throw an error. - * @returns {?*} Return-value of the function when no error occurred. - */ -module.exports = function(fn) { +Range.prototype.format = function() { + this.range = this.set.map(function(comps) { + return comps.join(' ').trim(); + }).join('||').trim(); + return this.range; +}; - try { return fn() } - catch (e) {} +Range.prototype.toString = function() { + return this.range; +}; -} +Range.prototype.parseRange = function(range) { + var loose = this.loose; + range = range.trim(); + debug('range', range, loose); + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; + range = range.replace(hr, hyphenReplace); + debug('hyphen replace', range); + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); + debug('comparator trim', range, re[COMPARATORTRIM]); -/***/ }), -/* 102 */ -/***/ (function(module, exports, __webpack_require__) { + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace); -"use strict"; + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace); + // normalize spaces + range = range.split(/\s+/).join(' '); -const path = __webpack_require__(16); -const which = __webpack_require__(103); -const pathKey = __webpack_require__(107)(); + // At this point, the range is completely trimmed and + // ready to be split into comparators. -function resolveCommandAttempt(parsed, withoutPathExt) { - const cwd = process.cwd(); - const hasCustomCwd = parsed.options.cwd != null; + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var set = range.split(' ').map(function(comp) { + return parseComparator(comp, loose); + }).join(' ').split(/\s+/); + if (this.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function(comp) { + return !!comp.match(compRe); + }); + } + set = set.map(function(comp) { + return new Comparator(comp, loose); + }); - // 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 (hasCustomCwd) { - try { - process.chdir(parsed.options.cwd); - } catch (err) { - /* Empty */ - } - } + return set; +}; - let resolved; +Range.prototype.intersects = function(range, loose) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required'); + } - try { - resolved = which.sync(parsed.command, { - path: (parsed.options.env || process.env)[pathKey], - pathExt: withoutPathExt ? path.delimiter : undefined, + return this.set.some(function(thisComparators) { + return thisComparators.every(function(thisComparator) { + return range.set.some(function(rangeComparators) { + return rangeComparators.every(function(rangeComparator) { + return thisComparator.intersects(rangeComparator, loose); }); - } catch (e) { - /* Empty */ - } finally { - process.chdir(cwd); - } + }); + }); + }); +}; - // 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); - } +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators; +function toComparators(range, loose) { + return new Range(range, loose).set.map(function(comp) { + return comp.map(function(c) { + return c.value; + }).join(' ').trim().split(' '); + }); +} - return resolved; +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator(comp, loose) { + debug('comp', comp); + comp = replaceCarets(comp, loose); + debug('caret', comp); + comp = replaceTildes(comp, loose); + debug('tildes', comp); + comp = replaceXRanges(comp, loose); + debug('xrange', comp); + comp = replaceStars(comp, loose); + debug('stars', comp); + return comp; } -function resolveCommand(parsed) { - return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); +function isX(id) { + return !id || id.toLowerCase() === 'x' || id === '*'; } -module.exports = resolveCommand; +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceTilde(comp, loose); + }).join(' '); +} +function replaceTilde(comp, loose) { + var r = loose ? re[TILDELOOSE] : re[TILDE]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr); + var ret; -/***/ }), -/* 103 */ -/***/ (function(module, exports, __webpack_require__) { + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + else if (isX(p)) + // ~1.2 == >=1.2.0 <1.3.0 + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + else if (pr) { + debug('replaceTilde pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0'; -module.exports = which -which.sync = whichSync + debug('tilde return', ret); + return ret; + }); +} -var isWindows = process.platform === 'win32' || - process.env.OSTYPE === 'cygwin' || - process.env.OSTYPE === 'msys' +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceCaret(comp, loose); + }).join(' '); +} -var path = __webpack_require__(16) -var COLON = isWindows ? ';' : ':' -var isexe = __webpack_require__(104) +function replaceCaret(comp, loose) { + debug('caret', comp, loose); + var r = loose ? re[CARETLOOSE] : re[CARET]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr); + var ret; -function getNotFoundError (cmd) { - var er = new Error('not found: ' + cmd) - er.code = 'ENOENT' + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + else if (isX(p)) { + if (M === '0') + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + else + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; + } else if (pr) { + debug('replaceCaret pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + if (M === '0') { + if (m === '0') + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + m + '.' + (+p + 1); + else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + (+M + 1) + '.0.0'; + } else { + debug('no pr'); + if (M === '0') { + if (m === '0') + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + m + '.' + (+p + 1); + else + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + ret = '>=' + M + '.' + m + '.' + p + + ' <' + (+M + 1) + '.0.0'; + } - return er + debug('caret return', ret); + return ret; + }); } -function getPathInfo (cmd, opt) { - var colon = opt.colon || COLON - var pathEnv = opt.path || process.env.PATH || '' - var pathExt = [''] +function replaceXRanges(comp, loose) { + debug('replaceXRanges', comp, loose); + return comp.split(/\s+/).map(function(comp) { + return replaceXRange(comp, loose); + }).join(' '); +} - pathEnv = pathEnv.split(colon) +function replaceXRange(comp, loose) { + comp = comp.trim(); + var r = loose ? re[XRANGELOOSE] : re[XRANGE]; + return comp.replace(r, function(ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr); + var xM = isX(M); + var xm = xM || isX(m); + var xp = xm || isX(p); + var anyX = xp; - var pathExtExe = '' - if (isWindows) { - pathEnv.unshift(process.cwd()) - pathExtExe = (opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM') - pathExt = pathExtExe.split(colon) + if (gtlt === '=' && anyX) + gtlt = ''; + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0'; + } else { + // nothing is forbidden + ret = '*'; + } + } else if (gtlt && anyX) { + // replace X with 0 + if (xm) + m = 0; + if (xp) + p = 0; - // Always test the cmd itself first. isexe will check to make sure - // it's found in the pathExt set. - if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') - pathExt.unshift('') - } + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + // >1.2.3 => >= 1.2.4 + gtlt = '>='; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else if (xp) { + m = +m + 1; + p = 0; + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<'; + if (xm) + M = +M + 1; + else + m = +m + 1; + } - // If it has a slash, then we don't bother searching the pathenv. - // just check the file itself, and that's it. - if (cmd.match(/\//) || isWindows && cmd.match(/\\/)) - pathEnv = [''] + ret = gtlt + M + '.' + m + '.' + p; + } else if (xm) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + } else if (xp) { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + } + + debug('xRange return', ret); - return { - env: pathEnv, - ext: pathExt, - extExe: pathExtExe - } + return ret; + }); } -function which (cmd, opt, cb) { - if (typeof opt === 'function') { - cb = opt - opt = {} - } +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars(comp, loose) { + debug('replaceStars', comp, loose); + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], ''); +} - var info = getPathInfo(cmd, opt) - var pathEnv = info.env - var pathExt = info.ext - var pathExtExe = info.extExe - var found = [] +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +function hyphenReplace($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { - ;(function F (i, l) { - if (i === l) { - if (opt.all && found.length) - return cb(null, found) - else - return cb(getNotFoundError(cmd)) - } + if (isX(fM)) + from = ''; + else if (isX(fm)) + from = '>=' + fM + '.0.0'; + else if (isX(fp)) + from = '>=' + fM + '.' + fm + '.0'; + else + from = '>=' + from; - var pathPart = pathEnv[i] - if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') - pathPart = pathPart.slice(1, -1) + if (isX(tM)) + to = ''; + else if (isX(tm)) + to = '<' + (+tM + 1) + '.0.0'; + else if (isX(tp)) + to = '<' + tM + '.' + (+tm + 1) + '.0'; + else if (tpr) + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; + else + to = '<=' + to; - var p = path.join(pathPart, cmd) - if (!pathPart && (/^\.[\\\/]/).test(cmd)) { - p = cmd.slice(0, 2) + p - } - ;(function E (ii, ll) { - if (ii === ll) return F(i + 1, l) - var ext = pathExt[ii] - isexe(p + ext, { pathExt: pathExtExe }, function (er, is) { - if (!er && is) { - if (opt.all) - found.push(p + ext) - else - return cb(null, p + ext) - } - return E(ii + 1, ll) - }) - })(0, pathExt.length) - })(0, pathEnv.length) + return (from + ' ' + to).trim(); } -function whichSync (cmd, opt) { - opt = opt || {} - var info = getPathInfo(cmd, opt) - var pathEnv = info.env - var pathExt = info.ext - var pathExtExe = info.extExe - var found = [] +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function(version) { + if (!version) + return false; - for (var i = 0, l = pathEnv.length; i < l; i ++) { - var pathPart = pathEnv[i] - if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') - pathPart = pathPart.slice(1, -1) + if (typeof version === 'string') + version = new SemVer(version, this.loose); - var p = path.join(pathPart, cmd) - if (!pathPart && /^\.[\\\/]/.test(cmd)) { - p = cmd.slice(0, 2) + p - } - for (var j = 0, ll = pathExt.length; j < ll; j ++) { - var cur = p + pathExt[j] - var is - try { - is = isexe.sync(cur, { pathExt: pathExtExe }) - if (is) { - if (opt.all) - found.push(cur) - else - return cur - } - } catch (ex) {} - } + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version)) + return true; } + return false; +}; - if (opt.all && found.length) - return found - - if (opt.nothrow) - return null +function testSet(set, version) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) + return false; + } - throw getNotFoundError(cmd) -} + if (version.prerelease.length) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (var i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === ANY) + continue; + if (set[i].semver.prerelease.length > 0) { + var allowed = set[i].semver; + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) + return true; + } + } -/***/ }), -/* 104 */ -/***/ (function(module, exports, __webpack_require__) { + // Version has a -pre, but it's not one of the ones we like. + return false; + } -var fs = __webpack_require__(23) -var core -if (process.platform === 'win32' || global.TESTING_WINDOWS) { - core = __webpack_require__(105) -} else { - core = __webpack_require__(106) + return true; } -module.exports = isexe -isexe.sync = sync - -function isexe (path, options, cb) { - if (typeof options === 'function') { - cb = options - options = {} +exports.satisfies = satisfies; +function satisfies(version, range, loose) { + try { + range = new Range(range, loose); + } catch (er) { + return false; } + return range.test(version); +} - if (!cb) { - if (typeof Promise !== 'function') { - throw new TypeError('callback not provided') +exports.maxSatisfying = maxSatisfying; +function maxSatisfying(versions, range, loose) { + var max = null; + var maxSV = null; + try { + var rangeObj = new Range(range, loose); + } catch (er) { + return null; + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { // satisfies(v, range, loose) + if (!max || maxSV.compare(v) === -1) { // compare(max, v, true) + max = v; + maxSV = new SemVer(max, loose); + } } + }) + return max; +} - return new Promise(function (resolve, reject) { - isexe(path, options || {}, function (er, is) { - if (er) { - reject(er) - } else { - resolve(is) - } - }) - }) +exports.minSatisfying = minSatisfying; +function minSatisfying(versions, range, loose) { + var min = null; + var minSV = null; + try { + var rangeObj = new Range(range, loose); + } catch (er) { + return null; } - - 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 + versions.forEach(function (v) { + if (rangeObj.test(v)) { // satisfies(v, range, loose) + if (!min || minSV.compare(v) === 1) { // compare(min, v, true) + min = v; + minSV = new SemVer(min, loose); } } - cb(er, is) }) + return min; } -function sync (path, options) { - // my kingdom for a filtered catch +exports.validRange = validRange; +function validRange(range, loose) { try { - return core.sync(path, options || {}) + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, loose).range || '*'; } catch (er) { - if (options && options.ignoreErrors || er.code === 'EACCES') { - return false - } else { - throw er - } + return null; } } +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr; +function ltr(version, range, loose) { + return outside(version, range, '<', loose); +} -/***/ }), -/* 105 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = isexe -isexe.sync = sync - -var fs = __webpack_require__(23) - -function checkPathExt (path, options) { - var pathext = options.pathExt !== undefined ? - options.pathExt : process.env.PATHEXT +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr; +function gtr(version, range, loose) { + return outside(version, range, '>', loose); +} - if (!pathext) { - return true - } +exports.outside = outside; +function outside(version, range, hilo, loose) { + version = new SemVer(version, loose); + range = new Range(range, loose); - 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 - } + var gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case '>': + gtfn = gt; + ltefn = lte; + ltfn = lt; + comp = '>'; + ecomp = '>='; + break; + case '<': + gtfn = lt; + ltefn = gte; + ltfn = gt; + comp = '<'; + ecomp = '<='; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); } - return false -} -function checkStat (stat, path, options) { - if (!stat.isSymbolicLink() && !stat.isFile()) { - return false + // If it satisifes the range it is not outside + if (satisfies(version, range, loose)) { + return false; } - return checkPathExt(path, options) -} - -function isexe (path, options, cb) { - fs.stat(path, function (er, stat) { - cb(er, er ? false : checkStat(stat, path, options)) - }) -} -function sync (path, options) { - return checkStat(fs.statSync(path), path, options) -} + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i]; -/***/ }), -/* 106 */ -/***/ (function(module, exports, __webpack_require__) { + var high = null; + var low = null; -module.exports = isexe -isexe.sync = sync + comparators.forEach(function(comparator) { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, loose)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, loose)) { + low = comparator; + } + }); -var fs = __webpack_require__(23) + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false; + } -function isexe (path, options, cb) { - fs.stat(path, function (er, stat) { - cb(er, er ? false : checkStat(stat, options)) - }) + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; } -function sync (path, options) { - return checkStat(fs.statSync(path), options) +exports.prerelease = prerelease; +function prerelease(version, loose) { + var parsed = parse(version, loose); + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; } -function checkStat (stat, options) { - return stat.isFile() && checkMode(stat, options) +exports.intersects = intersects; +function intersects(r1, r2, loose) { + r1 = new Range(r1, loose) + r2 = new Range(r2, loose) + return r1.intersects(r2) } -function checkMode (stat, options) { - var mod = stat.mode - var uid = stat.uid - var gid = stat.gid +exports.coerce = coerce; +function coerce(version) { + if (version instanceof SemVer) + return version; - var myUid = options.uid !== undefined ? - options.uid : process.getuid && process.getuid() - var myGid = options.gid !== undefined ? - options.gid : process.getgid && process.getgid() + if (typeof version !== 'string') + return null; - var u = parseInt('100', 8) - var g = parseInt('010', 8) - var o = parseInt('001', 8) - var ug = u | g + var match = version.match(re[COERCE]); - var ret = (mod & o) || - (mod & g) && gid === myGid || - (mod & u) && uid === myUid || - (mod & ug) && myUid === 0 + if (match == null) + return null; - return ret + return parse((match[1] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0')); } /***/ }), -/* 107 */ +/* 137 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = opts => { - opts = opts || {}; - - const env = opts.env || process.env; - const platform = opts.platform || process.platform; - if (platform !== 'win32') { - return 'PATH'; - } +const isWin = process.platform === 'win32'; - return Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; -}; +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 hookChildProcess(cp, parsed) { + if (!isWin) { + return; + } -/***/ }), -/* 108 */ -/***/ (function(module, exports, __webpack_require__) { + const originalEmit = cp.emit; -"use strict"; + 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'); + if (err) { + return originalEmit.call(cp, 'error', err); + } + } -// See http://www.robvanderwoude.com/escapechars.php -const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; + return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params + }; +} -function escapeCommand(arg) { - // Escape meta chars - arg = arg.replace(metaCharsRegExp, '^$1'); +function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawn'); + } - return arg; + return null; } -function escapeArgument(arg, doubleEscapeMetaChars) { - // Convert to string - arg = `${arg}`; +function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); + } - // Algorithm below is based on https://qntm.org/cmd + return null; +} - // Sequence of backslashes followed by a double quote: - // double up all the backslashes and escape the double quote - arg = arg.replace(/(\\*)"/g, '$1$1\\"'); +module.exports = { + hookChildProcess, + verifyENOENT, + verifyENOENTSync, + notFoundError, +}; - // 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'); - // All other backslashes occur literally +/***/ }), +/* 138 */ +/***/ (function(module, exports, __webpack_require__) { - // Quote the whole thing: - arg = `"${arg}"`; +"use strict"; - // Escape meta chars - arg = arg.replace(metaCharsRegExp, '^$1'); +module.exports = function (x) { + var lf = typeof x === 'string' ? '\n' : '\n'.charCodeAt(); + var cr = typeof x === 'string' ? '\r' : '\r'.charCodeAt(); - // Double escape meta chars if necessary - if (doubleEscapeMetaChars) { - arg = arg.replace(metaCharsRegExp, '^$1'); - } + if (x[x.length - 1] === lf) { + x = x.slice(0, x.length - 1); + } - return arg; -} + if (x[x.length - 1] === cr) { + x = x.slice(0, x.length - 1); + } -module.exports.command = escapeCommand; -module.exports.argument = escapeArgument; + return x; +}; /***/ }), -/* 109 */ +/* 139 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const path = __webpack_require__(16); +const pathKey = __webpack_require__(140); + +module.exports = opts => { + opts = Object.assign({ + cwd: process.cwd(), + path: process.env[pathKey()] + }, opts); + + let prev; + let pth = path.resolve(opts.cwd); + const ret = []; -const fs = __webpack_require__(23); -const shebangCommand = __webpack_require__(110); + while (prev !== pth) { + ret.push(path.join(pth, 'node_modules/.bin')); + prev = pth; + pth = path.resolve(pth, '..'); + } -function readShebang(command) { - // Read the first 150 bytes from the file - const size = 150; - let buffer; + // ensure the running `node` binary is used + ret.push(path.dirname(process.execPath)); - if (Buffer.alloc) { - // Node.js v4.5+ / v5.10+ - buffer = Buffer.alloc(size); - } else { - // Old Node.js API - buffer = new Buffer(size); - buffer.fill(0); // zero-fill - } + return ret.concat(opts.path).join(path.delimiter); +}; - let fd; +module.exports.env = opts => { + opts = Object.assign({ + env: process.env + }, opts); - try { - fd = fs.openSync(command, 'r'); - fs.readSync(fd, buffer, 0, size, 0); - fs.closeSync(fd); - } catch (e) { /* Empty */ } + const env = Object.assign({}, opts.env); + const path = pathKey({env}); - // Attempt to extract shebang (null is returned if not a shebang) - return shebangCommand(buffer.toString()); -} + opts.path = env[path]; + env[path] = module.exports(opts); -module.exports = readShebang; + return env; +}; /***/ }), -/* 110 */ +/* 140 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var shebangRegex = __webpack_require__(111); +module.exports = opts => { + opts = opts || {}; -module.exports = function (str) { - var match = str.match(shebangRegex); + const env = opts.env || process.env; + const platform = opts.platform || process.platform; - if (!match) { - return null; + if (platform !== 'win32') { + return 'PATH'; } - var arr = match[0].replace(/#! ?/, '').split(' '); - var bin = arr[0].split('/').pop(); - var arg = arr[1]; - - return (bin === 'env' ? - arg : - bin + (arg ? ' ' + arg : '') - ); + return Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; }; /***/ }), -/* 111 */ +/* 141 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = /^#!.*/; +var isStream = module.exports = function (stream) { + return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function'; +}; -/***/ }), -/* 112 */ -/***/ (function(module, exports) { +isStream.writable = function (stream) { + return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object'; +}; -exports = module.exports = SemVer; +isStream.readable = function (stream) { + return isStream(stream) && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object'; +}; -// The debug function is excluded entirely from the minified version. -/* nomin */ var debug; -/* nomin */ if (typeof process === 'object' && - /* nomin */ process.env && - /* nomin */ process.env.NODE_DEBUG && - /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) - /* nomin */ debug = function() { - /* nomin */ var args = Array.prototype.slice.call(arguments, 0); - /* nomin */ args.unshift('SEMVER'); - /* nomin */ console.log.apply(console, args); - /* nomin */ }; -/* nomin */ else - /* nomin */ debug = function() {}; +isStream.duplex = function (stream) { + return isStream.writable(stream) && isStream.readable(stream); +}; -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0'; +isStream.transform = function (stream) { + return isStream.duplex(stream) && typeof stream._transform === 'function' && typeof stream._transformState === 'object'; +}; -var MAX_LENGTH = 256; -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; -// Max safe segment length for coercion. -var MAX_SAFE_COMPONENT_LENGTH = 16; +/***/ }), +/* 142 */ +/***/ (function(module, exports, __webpack_require__) { -// The actual regexps go on exports.re -var re = exports.re = []; -var src = exports.src = []; -var R = 0; +"use strict"; -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. +const pump = __webpack_require__(143); +const bufferStream = __webpack_require__(145); -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. +class MaxBufferError extends Error { + constructor() { + super('maxBuffer exceeded'); + this.name = 'MaxBufferError'; + } +} -var NUMERICIDENTIFIER = R++; -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; -var NUMERICIDENTIFIERLOOSE = R++; -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; +function getStream(inputStream, options) { + if (!inputStream) { + return Promise.reject(new Error('Expected a stream')); + } + options = Object.assign({maxBuffer: Infinity}, options); -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. + const {maxBuffer} = options; -var NONNUMERICIDENTIFIER = R++; -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; + let stream; + return new Promise((resolve, reject) => { + const rejectPromise = error => { + if (error) { // A null check + error.bufferedData = stream.getBufferedValue(); + } + reject(error); + }; + stream = pump(inputStream, bufferStream(options), error => { + if (error) { + rejectPromise(error); + return; + } -// ## Main Version -// Three dot-separated numeric identifiers. + resolve(); + }); -var MAINVERSION = R++; -src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')'; + stream.on('data', () => { + if (stream.getBufferedLength() > maxBuffer) { + rejectPromise(new MaxBufferError()); + } + }); + }).then(() => stream.getBufferedValue()); +} -var MAINVERSIONLOOSE = R++; -src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; +module.exports = getStream; +module.exports.buffer = (stream, options) => getStream(stream, Object.assign({}, options, {encoding: 'buffer'})); +module.exports.array = (stream, options) => getStream(stream, Object.assign({}, options, {array: true})); +module.exports.MaxBufferError = MaxBufferError; -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. -var PRERELEASEIDENTIFIER = R++; -src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; +/***/ }), +/* 143 */ +/***/ (function(module, exports, __webpack_require__) { -var PRERELEASEIDENTIFIERLOOSE = R++; -src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; +var once = __webpack_require__(52) +var eos = __webpack_require__(144) +var fs = __webpack_require__(23) // we only need fs to get the ReadStream and WriteStream prototypes +var noop = function () {} +var ancient = /^v?\.0/.test(process.version) -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. +var isFn = function (fn) { + return typeof fn === 'function' +} -var PRERELEASE = R++; -src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; +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 PRERELEASELOOSE = R++; -src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; +var isRequest = function (stream) { + return stream.setHeader && isFn(stream.abort) +} -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. +var destroyer = function (stream, reading, writing, callback) { + callback = once(callback) -var BUILDIDENTIFIER = R++; -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; + var closed = false + stream.on('close', function () { + closed = true + }) -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. + eos(stream, {readable: reading, writable: writing}, function (err) { + if (err) return callback(err) + closed = true + callback() + }) -var BUILD = R++; -src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; + 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 -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. + if (isFn(stream.destroy)) return stream.destroy() -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. + callback(err || new Error('stream was destroyed')) + } +} -var FULL = R++; -var FULLPLAIN = 'v?' + src[MAINVERSION] + - src[PRERELEASE] + '?' + - src[BUILD] + '?'; +var call = function (fn) { + fn() +} -src[FULL] = '^' + FULLPLAIN + '$'; +var pipe = function (from, to) { + return from.pipe(to) +} -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + - src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?'; +var pump = function () { + var streams = Array.prototype.slice.call(arguments) + var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop -var LOOSE = R++; -src[LOOSE] = '^' + LOOSEPLAIN + '$'; + if (Array.isArray(streams[0])) streams = streams[0] + if (streams.length < 2) throw new Error('pump requires two streams per minimum') -var GTLT = R++; -src[GTLT] = '((?:<|>)?=?)'; + 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) + }) + }) -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++; -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; -var XRANGEIDENTIFIER = R++; -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; + return streams.reduce(pipe) +} -var XRANGEPLAIN = R++; -src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:' + src[PRERELEASE] + ')?' + - src[BUILD] + '?' + - ')?)?'; +module.exports = pump -var XRANGEPLAINLOOSE = R++; -src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[PRERELEASELOOSE] + ')?' + - src[BUILD] + '?' + - ')?)?'; -var XRANGE = R++; -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; -var XRANGELOOSE = R++; -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; +/***/ }), +/* 144 */ +/***/ (function(module, exports, __webpack_require__) { -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -var COERCE = R++; -src[COERCE] = '(?:^|[^\\d])' + - '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:$|[^\\d])'; +var once = __webpack_require__(52); -// Tilde ranges. -// Meaning is "reasonably at or greater than" -var LONETILDE = R++; -src[LONETILDE] = '(?:~>?)'; +var noop = function() {}; -var TILDETRIM = R++; -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); -var tildeTrimReplace = '$1~'; +var isRequest = function(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +}; -var TILDE = R++; -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; -var TILDELOOSE = R++; -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; +var isChildProcess = function(stream) { + return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 +}; -// Caret ranges. -// Meaning is "at least and backwards compatible with" -var LONECARET = R++; -src[LONECARET] = '(?:\\^)'; +var eos = function(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; -var CARETTRIM = R++; -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); -var caretTrimReplace = '$1^'; + callback = once(callback || noop); -var CARET = R++; -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; -var CARETLOOSE = R++; -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; + 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); -// A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++; -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; -var COMPARATOR = R++; -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + var onlegacyfinish = function() { + if (!stream.writable) onfinish(); + }; + var onfinish = function() { + writable = false; + if (!readable) callback.call(stream); + }; -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++; -src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + var onend = function() { + readable = false; + if (!writable) callback.call(stream); + }; -// this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); -var comparatorTrimReplace = '$1$2$3'; + var onexit = function(exitCode) { + callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); + }; + var onerror = function(err) { + callback.call(stream, err); + }; -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -var HYPHENRANGE = R++; -src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAIN] + ')' + - '\\s*$'; + var onclose = function() { + if (readable && !(rs && rs.ended)) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && ws.ended)) return callback.call(stream, new Error('premature close')); + }; -var HYPHENRANGELOOSE = R++; -src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$'; + var onrequest = function() { + stream.req.on('finish', onfinish); + }; -// Star ranges basically just allow anything at all. -var STAR = R++; -src[STAR] = '(<|>)?=?\\s*\\*'; + 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); + } -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]); - if (!re[i]) - re[i] = new RegExp(src[i]); -} + if (isChildProcess(stream)) stream.on('exit', onexit); -exports.parse = parse; -function parse(version, loose) { - if (version instanceof SemVer) - return version; + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); - if (typeof version !== 'string') - return null; + return function() { + 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); + }; +}; - if (version.length > MAX_LENGTH) - return null; +module.exports = eos; - var r = loose ? re[LOOSE] : re[FULL]; - if (!r.test(version)) - return null; - try { - return new SemVer(version, loose); - } catch (er) { - return null; - } -} +/***/ }), +/* 145 */ +/***/ (function(module, exports, __webpack_require__) { -exports.valid = valid; -function valid(version, loose) { - var v = parse(version, loose); - return v ? v.version : null; -} +"use strict"; +const {PassThrough} = __webpack_require__(28); -exports.clean = clean; -function clean(version, loose) { - var s = parse(version.trim().replace(/^[=v]+/, ''), loose); - return s ? s.version : null; -} +module.exports = options => { + options = Object.assign({}, options); -exports.SemVer = SemVer; + const {array} = options; + let {encoding} = options; + const buffer = encoding === 'buffer'; + let objectMode = false; -function SemVer(version, loose) { - if (version instanceof SemVer) { - if (version.loose === loose) - return version; - else - version = version.version; - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version); - } + if (array) { + objectMode = !(encoding || buffer); + } else { + encoding = encoding || 'utf8'; + } + + if (buffer) { + encoding = null; + } - if (version.length > MAX_LENGTH) - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + let len = 0; + const ret = []; + const stream = new PassThrough({objectMode}); - if (!(this instanceof SemVer)) - return new SemVer(version, loose); + if (encoding) { + stream.setEncoding(encoding); + } - debug('SemVer', version, loose); - this.loose = loose; - var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + stream.on('data', chunk => { + ret.push(chunk); - if (!m) - throw new TypeError('Invalid Version: ' + version); + if (objectMode) { + len = ret.length; + } else { + len += chunk.length; + } + }); - this.raw = version; + stream.getBufferedValue = () => { + if (array) { + return ret; + } - // these are actually numbers - this.major = +m[1]; - this.minor = +m[2]; - this.patch = +m[3]; + return buffer ? Buffer.concat(ret, len) : ret.join(''); + }; - if (this.major > MAX_SAFE_INTEGER || this.major < 0) - throw new TypeError('Invalid major version') + stream.getBufferedLength = () => len; - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) - throw new TypeError('Invalid minor version') + return stream; +}; - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) - throw new TypeError('Invalid patch version') - // numberify any prerelease numeric ids - if (!m[4]) - this.prerelease = []; - else - this.prerelease = m[4].split('.').map(function(id) { - if (/^[0-9]+$/.test(id)) { - var num = +id; - if (num >= 0 && num < MAX_SAFE_INTEGER) - return num; - } - return id; - }); +/***/ }), +/* 146 */ +/***/ (function(module, exports, __webpack_require__) { - this.build = m[5] ? m[5].split('.') : []; - this.format(); -} +"use strict"; -SemVer.prototype.format = function() { - this.version = this.major + '.' + this.minor + '.' + this.patch; - if (this.prerelease.length) - this.version += '-' + this.prerelease.join('.'); - return this.version; -}; +module.exports = (promise, onFinally) => { + onFinally = onFinally || (() => {}); -SemVer.prototype.toString = function() { - return this.version; + return promise.then( + val => new Promise(resolve => { + resolve(onFinally()); + }).then(() => val), + err => new Promise(resolve => { + resolve(onFinally()); + }).then(() => { + throw err; + }) + ); }; -SemVer.prototype.compare = function(other) { - debug('SemVer.compare', this.version, this.loose, other); - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); - return this.compareMain(other) || this.comparePre(other); -}; +/***/ }), +/* 147 */ +/***/ (function(module, exports, __webpack_require__) { -SemVer.prototype.compareMain = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +"use strict"; - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch); -}; +// Older verions of Node.js might not have `util.getSystemErrorName()`. +// In that case, fall back to a deprecated internal. +const util = __webpack_require__(29); -SemVer.prototype.comparePre = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +let uv; - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) - return -1; - else if (!this.prerelease.length && other.prerelease.length) - return 1; - else if (!this.prerelease.length && !other.prerelease.length) - return 0; +if (typeof util.getSystemErrorName === 'function') { + module.exports = util.getSystemErrorName; +} else { + try { + uv = process.binding('uv'); - var i = 0; - do { - var a = this.prerelease[i]; - var b = other.prerelease[i]; - debug('prerelease compare', i, a, b); - if (a === undefined && b === undefined) - return 0; - else if (b === undefined) - return 1; - else if (a === undefined) - return -1; - else if (a === b) - continue; - else - return compareIdentifiers(a, b); - } while (++i); -}; + if (typeof uv.errname !== 'function') { + throw new TypeError('uv.errname is not a function'); + } + } catch (err) { + console.error('execa/lib/errname: unable to establish process.binding(\'uv\')', err); + uv = null; + } -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function(release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0; - this.patch = 0; - this.minor = 0; - this.major++; - this.inc('pre', identifier); - break; - case 'preminor': - this.prerelease.length = 0; - this.patch = 0; - this.minor++; - this.inc('pre', identifier); - break; - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0; - this.inc('patch', identifier); - this.inc('pre', identifier); - break; - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) - this.inc('patch', identifier); - this.inc('pre', identifier); - break; + module.exports = code => errname(uv, code); +} - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) - this.major++; - this.minor = 0; - this.patch = 0; - this.prerelease = []; - break; - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) - this.minor++; - this.patch = 0; - this.prerelease = []; - break; - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) - this.patch++; - this.prerelease = []; - break; - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) - this.prerelease = [0]; - else { - var i = this.prerelease.length; - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++; - i = -2; - } - } - if (i === -1) // didn't increment anything - this.prerelease.push(0); - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) - this.prerelease = [identifier, 0]; - } else - this.prerelease = [identifier, 0]; - } - break; +// Used for testing the fallback behavior +module.exports.__test__ = errname; - default: - throw new Error('invalid increment argument: ' + release); - } - this.format(); - this.raw = this.version; - return this; -}; +function errname(uv, code) { + if (uv) { + return uv.errname(code); + } -exports.inc = inc; -function inc(version, release, loose, identifier) { - if (typeof(loose) === 'string') { - identifier = loose; - loose = undefined; - } + if (!(code < 0)) { + throw new Error('err >= 0'); + } - try { - return new SemVer(version, loose).inc(release, identifier).version; - } catch (er) { - return null; - } + return `Unknown system error ${code}`; } -exports.diff = diff; -function diff(version1, version2) { - if (eq(version1, version2)) { - return null; - } else { - var v1 = parse(version1); - var v2 = parse(version2); - if (v1.prerelease.length || v2.prerelease.length) { - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return 'pre'+key; - } - } - } - return 'prerelease'; - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return key; - } - } - } - } -} -exports.compareIdentifiers = compareIdentifiers; -var numeric = /^[0-9]+$/; -function compareIdentifiers(a, b) { - var anum = numeric.test(a); - var bnum = numeric.test(b); +/***/ }), +/* 148 */ +/***/ (function(module, exports, __webpack_require__) { - if (anum && bnum) { - a = +a; - b = +b; - } +"use strict"; - return (anum && !bnum) ? -1 : - (bnum && !anum) ? 1 : - a < b ? -1 : - a > b ? 1 : - 0; -} +const alias = ['stdin', 'stdout', 'stderr']; -exports.rcompareIdentifiers = rcompareIdentifiers; -function rcompareIdentifiers(a, b) { - return compareIdentifiers(b, a); -} +const hasAlias = opts => alias.some(x => Boolean(opts[x])); -exports.major = major; -function major(a, loose) { - return new SemVer(a, loose).major; -} +module.exports = opts => { + if (!opts) { + return null; + } -exports.minor = minor; -function minor(a, loose) { - return new SemVer(a, loose).minor; -} + if (opts.stdio && hasAlias(opts)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${alias.map(x => `\`${x}\``).join(', ')}`); + } -exports.patch = patch; -function patch(a, loose) { - return new SemVer(a, loose).patch; -} + if (typeof opts.stdio === 'string') { + return opts.stdio; + } -exports.compare = compare; -function compare(a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)); -} + const stdio = opts.stdio || []; -exports.compareLoose = compareLoose; -function compareLoose(a, b) { - return compare(a, b, true); -} + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + } -exports.rcompare = rcompare; -function rcompare(a, b, loose) { - return compare(b, a, loose); -} + const result = []; + const len = Math.max(stdio.length, alias.length); -exports.sort = sort; -function sort(list, loose) { - return list.sort(function(a, b) { - return exports.compare(a, b, loose); - }); -} + for (let i = 0; i < len; i++) { + let value = null; -exports.rsort = rsort; -function rsort(list, loose) { - return list.sort(function(a, b) { - return exports.rcompare(a, b, loose); - }); -} + if (stdio[i] !== undefined) { + value = stdio[i]; + } else if (opts[alias[i]] !== undefined) { + value = opts[alias[i]]; + } -exports.gt = gt; -function gt(a, b, loose) { - return compare(a, b, loose) > 0; -} + result[i] = value; + } -exports.lt = lt; -function lt(a, b, loose) { - return compare(a, b, loose) < 0; -} + return result; +}; -exports.eq = eq; -function eq(a, b, loose) { - return compare(a, b, loose) === 0; -} -exports.neq = neq; -function neq(a, b, loose) { - return compare(a, b, loose) !== 0; -} +/***/ }), +/* 149 */ +/***/ (function(module, exports, __webpack_require__) { -exports.gte = gte; -function gte(a, b, loose) { - return compare(a, b, loose) >= 0; -} +"use strict"; -exports.lte = lte; -function lte(a, b, loose) { - return compare(a, b, loose) <= 0; -} +const chalk = __webpack_require__(150); -exports.cmp = cmp; -function cmp(a, op, b, loose) { - var ret; - switch (op) { - case '===': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a === b; - break; - case '!==': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a !== b; - break; - case '': case '=': case '==': ret = eq(a, b, loose); break; - case '!=': ret = neq(a, b, loose); break; - case '>': ret = gt(a, b, loose); break; - case '>=': ret = gte(a, b, loose); break; - case '<': ret = lt(a, b, loose); break; - case '<=': ret = lte(a, b, loose); break; - default: throw new TypeError('Invalid operator: ' + op); - } - return ret; -} +const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; -exports.Comparator = Comparator; -function Comparator(comp, loose) { - if (comp instanceof Comparator) { - if (comp.loose === loose) - return comp; - else - comp = comp.value; - } +const main = { + info: chalk.blue('ℹ'), + success: chalk.green('✔'), + warning: chalk.yellow('⚠'), + error: chalk.red('✖') +}; - if (!(this instanceof Comparator)) - return new Comparator(comp, loose); +const fallbacks = { + info: chalk.blue('i'), + success: chalk.green('√'), + warning: chalk.yellow('‼'), + error: chalk.red('×') +}; - debug('comparator', comp, loose); - this.loose = loose; - this.parse(comp); +module.exports = isSupported ? main : fallbacks; - if (this.semver === ANY) - this.value = ''; - else - this.value = this.operator + this.semver.version; - debug('comp', this); -} +/***/ }), +/* 150 */ +/***/ (function(module, exports, __webpack_require__) { -var ANY = {}; -Comparator.prototype.parse = function(comp) { - var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var m = comp.match(r); +"use strict"; - if (!m) - throw new TypeError('Invalid comparator: ' + comp); +const escapeStringRegexp = __webpack_require__(3); +const ansiStyles = __webpack_require__(151); +const stdoutColor = __webpack_require__(152).stdout; - this.operator = m[1]; - if (this.operator === '=') - this.operator = ''; +const template = __webpack_require__(153); - // if it literally is just '>' or '' then allow anything. - if (!m[2]) - this.semver = ANY; - else - this.semver = new SemVer(m[2], this.loose); -}; +const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); -Comparator.prototype.toString = function() { - return this.value; -}; +// `supportsColor.level` → `ansiStyles.color[name]` mapping +const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; -Comparator.prototype.test = function(version) { - debug('Comparator.test', version, this.loose); +// `color-convert` models to exclude from the Chalk API due to conflicts and such +const skipModels = new Set(['gray']); - if (this.semver === ANY) - return true; +const styles = Object.create(null); - if (typeof version === 'string') - version = new SemVer(version, this.loose); +function applyOptions(obj, options) { + options = options || {}; - return cmp(version, this.operator, this.semver, this.loose); -}; + // 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); -Comparator.prototype.intersects = function(comp, loose) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required'); - } + chalk.template = function () { + const args = [].slice.call(arguments); + return chalkTag.apply(null, [chalk.template].concat(args)); + }; - var rangeTmp; + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); - if (this.operator === '') { - rangeTmp = new Range(comp.value, loose); - return satisfies(this.value, rangeTmp, loose); - } else if (comp.operator === '') { - rangeTmp = new Range(this.value, loose); - return satisfies(comp.semver, rangeTmp, loose); - } + chalk.template.constructor = Chalk; - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>'); - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<'); - var sameSemVer = this.semver.version === comp.semver.version; - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<='); - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, loose) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')); - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, loose) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')); + return chalk.template; + } - return sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; -}; + applyOptions(this, options); +} +// Use bright blue on Windows as the normal blue color is illegible +if (isSimpleWindowsTerm) { + ansiStyles.blue.open = '\u001B[94m'; +} -exports.Range = Range; -function Range(range, loose) { - if (range instanceof Range) { - if (range.loose === loose) { - return range; - } else { - return new Range(range.raw, loose); - } - } +for (const key of Object.keys(ansiStyles)) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); - if (range instanceof Comparator) { - return new Range(range.value, loose); - } + styles[key] = { + get() { + const codes = ansiStyles[key]; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); + } + }; +} - if (!(this instanceof Range)) - return new Range(range, loose); +styles.visible = { + get() { + return build.call(this, this._styles || [], true, 'visible'); + } +}; - this.loose = loose; +ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); +for (const model of Object.keys(ansiStyles.color.ansi)) { + if (skipModels.has(model)) { + continue; + } - // First, split based on boolean or || - this.raw = range; - this.set = range.split(/\s*\|\|\s*/).map(function(range) { - return this.parseRange(range.trim()); - }, this).filter(function(c) { - // throw out any that are not relevant for whatever reason - return c.length; - }); + 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); + }; + } + }; +} - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range); - } +ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); +for (const model of Object.keys(ansiStyles.bgColor.ansi)) { + if (skipModels.has(model)) { + continue; + } - this.format(); + 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); + }; + } + }; } -Range.prototype.format = function() { - this.range = this.set.map(function(comps) { - return comps.join(' ').trim(); - }).join('||').trim(); - return this.range; -}; +const proto = Object.defineProperties(() => {}, styles); -Range.prototype.toString = function() { - return this.range; -}; +function build(_styles, _empty, key) { + const builder = function () { + return applyStyle.apply(builder, arguments); + }; -Range.prototype.parseRange = function(range) { - var loose = this.loose; - range = range.trim(); - debug('range', range, loose); - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; - range = range.replace(hr, hyphenReplace); - debug('hyphen replace', range); - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); - debug('comparator trim', range, re[COMPARATORTRIM]); + builder._styles = _styles; + builder._empty = _empty; - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace); + const self = this; - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace); + Object.defineProperty(builder, 'level', { + enumerable: true, + get() { + return self.level; + }, + set(level) { + self.level = level; + } + }); - // normalize spaces - range = range.split(/\s+/).join(' '); + Object.defineProperty(builder, 'enabled', { + enumerable: true, + get() { + return self.enabled; + }, + set(enabled) { + self.enabled = enabled; + } + }); - // At this point, the range is completely trimmed and - // ready to be split into comparators. + // See below for fix regarding invisible grey/dim combination on Windows + builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var set = range.split(' ').map(function(comp) { - return parseComparator(comp, loose); - }).join(' ').split(/\s+/); - if (this.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function(comp) { - return !!comp.match(compRe); - }); - } - set = set.map(function(comp) { - return new Comparator(comp, loose); - }); + // `__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 set; -}; + return builder; +} -Range.prototype.intersects = function(range, loose) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required'); - } +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]); - return this.set.some(function(thisComparators) { - return thisComparators.every(function(thisComparator) { - return range.set.some(function(rangeComparators) { - return rangeComparators.every(function(rangeComparator) { - return thisComparator.intersects(rangeComparator, loose); - }); - }); - }); - }); -}; + if (argsLen === 0) { + return ''; + } -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators; -function toComparators(range, loose) { - return new Range(range, loose).set.map(function(comp) { - return comp.map(function(c) { - return c.value; - }).join(' ').trim().split(' '); - }); -} + if (argsLen > 1) { + // Don't slice `arguments`, it prevents V8 optimizations + for (let a = 1; a < argsLen; a++) { + str += ' ' + args[a]; + } + } -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator(comp, loose) { - debug('comp', comp); - comp = replaceCarets(comp, loose); - debug('caret', comp); - comp = replaceTildes(comp, loose); - debug('tildes', comp); - comp = replaceXRanges(comp, loose); - debug('xrange', comp); - comp = replaceStars(comp, loose); - debug('stars', comp); - return comp; -} + if (!this.enabled || this.level <= 0 || !str) { + return this._empty ? '' : str; + } -function isX(id) { - return !id || id.toLowerCase() === 'x' || id === '*'; -} + // 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 = ''; + } -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceTilde(comp, loose); - }).join(' '); -} + 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; -function replaceTilde(comp, loose) { - var r = loose ? re[TILDELOOSE] : re[TILDE]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr); - var ret; + // 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}`); + } - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else if (pr) { - debug('replaceTilde pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; + // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue + ansiStyles.dim.open = originalDim; - debug('tilde return', ret); - return ret; - }); + return str; } -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceCaret(comp, loose); - }).join(' '); -} +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(' '); + } -function replaceCaret(comp, loose) { - debug('caret', comp, loose); - var r = loose ? re[CARETLOOSE] : re[CARET]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr); - var ret; + const args = [].slice.call(arguments, 2); + const parts = [strings.raw[0]]; - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) { - if (M === '0') - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; - } else if (pr) { - debug('replaceCaret pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + (+M + 1) + '.0.0'; - } else { - debug('no pr'); - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0'; - } + for (let i = 1; i < strings.length; i++) { + parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&')); + parts.push(String(strings.raw[i])); + } - debug('caret return', ret); - return ret; - }); + return template(chalk, parts.join('')); } -function replaceXRanges(comp, loose) { - debug('replaceXRanges', comp, loose); - return comp.split(/\s+/).map(function(comp) { - return replaceXRange(comp, loose); - }).join(' '); -} +Object.defineProperties(Chalk.prototype, styles); -function replaceXRange(comp, loose) { - comp = comp.trim(); - var r = loose ? re[XRANGELOOSE] : re[XRANGE]; - return comp.replace(r, function(ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr); - var xM = isX(M); - var xm = xM || isX(m); - var xp = xm || isX(p); - var anyX = xp; +module.exports = Chalk(); // eslint-disable-line new-cap +module.exports.supportsColor = stdoutColor; +module.exports.default = module.exports; // For TypeScript - if (gtlt === '=' && anyX) - gtlt = ''; - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0'; - } else { - // nothing is forbidden - ret = '*'; - } - } else if (gtlt && anyX) { - // replace X with 0 - if (xm) - m = 0; - if (xp) - p = 0; +/***/ }), +/* 151 */ +/***/ (function(module, exports, __webpack_require__) { - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>='; - if (xm) { - M = +M + 1; - m = 0; - p = 0; - } else if (xp) { - m = +m + 1; - p = 0; - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<'; - if (xm) - M = +M + 1; - else - m = +m + 1; - } +"use strict"; +/* WEBPACK VAR INJECTION */(function(module) { +const colorConvert = __webpack_require__(6); - ret = gtlt + M + '.' + m + '.' + p; - } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - } +const wrapAnsi16 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${code + offset}m`; +}; - debug('xRange return', ret); +const wrapAnsi256 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${38 + offset};5;${code}m`; +}; - return ret; - }); -} +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], -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars(comp, loose) { - debug('replaceStars', comp, loose); - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], ''); -} + // 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] + } + }; -// This function is passed to string.replace(re[HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { + // Fix humans + styles.color.grey = styles.color.gray; - if (isX(fM)) - from = ''; - else if (isX(fm)) - from = '>=' + fM + '.0.0'; - else if (isX(fp)) - from = '>=' + fM + '.' + fm + '.0'; - else - from = '>=' + from; + for (const groupName of Object.keys(styles)) { + const group = styles[groupName]; - if (isX(tM)) - to = ''; - else if (isX(tm)) - to = '<' + (+tM + 1) + '.0.0'; - else if (isX(tp)) - to = '<' + tM + '.' + (+tm + 1) + '.0'; - else if (tpr) - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; - else - to = '<=' + to; + for (const styleName of Object.keys(group)) { + const style = group[styleName]; - return (from + ' ' + to).trim(); -} + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m` + }; + group[styleName] = styles[styleName]; -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function(version) { - if (!version) - return false; + codes.set(style[0], style[1]); + } - if (typeof version === 'string') - version = new SemVer(version, this.loose); + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version)) - return true; - } - return false; -}; + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); + } -function testSet(set, version) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) - return false; - } + const ansi2ansi = n => n; + const rgb2rgb = (r, g, b) => [r, g, b]; - if (version.prerelease.length) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (var i = 0; i < set.length; i++) { - debug(set[i].semver); - if (set[i].semver === ANY) - continue; + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver; - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) - return true; - } - } + styles.color.ansi = { + ansi: wrapAnsi16(ansi2ansi, 0) + }; + styles.color.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 0) + }; + styles.color.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 0) + }; - // Version has a -pre, but it's not one of the ones we like. - return false; - } + styles.bgColor.ansi = { + ansi: wrapAnsi16(ansi2ansi, 10) + }; + styles.bgColor.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 10) + }; + styles.bgColor.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 10) + }; - return true; -} + for (let key of Object.keys(colorConvert)) { + if (typeof colorConvert[key] !== 'object') { + continue; + } -exports.satisfies = satisfies; -function satisfies(version, range, loose) { - try { - range = new Range(range, loose); - } catch (er) { - return false; - } - return range.test(version); -} + const suite = colorConvert[key]; -exports.maxSatisfying = maxSatisfying; -function maxSatisfying(versions, range, loose) { - var max = null; - var maxSV = null; - try { - var rangeObj = new Range(range, loose); - } catch (er) { - return null; - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!max || maxSV.compare(v) === -1) { // compare(max, v, true) - max = v; - maxSV = new SemVer(max, loose); - } - } - }) - return max; -} + if (key === 'ansi16') { + key = 'ansi'; + } -exports.minSatisfying = minSatisfying; -function minSatisfying(versions, range, loose) { - var min = null; - var minSV = null; - try { - var rangeObj = new Range(range, loose); - } catch (er) { - return null; - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!min || minSV.compare(v) === 1) { // compare(min, v, true) - min = v; - minSV = new SemVer(min, loose); - } - } - }) - return min; -} + if ('ansi16' in suite) { + styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0); + styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10); + } -exports.validRange = validRange; -function validRange(range, loose) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, loose).range || '*'; - } catch (er) { - return null; - } -} + if ('ansi256' in suite) { + styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0); + styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10); + } -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr; -function ltr(version, range, loose) { - return outside(version, range, '<', loose); -} + if ('rgb' in suite) { + styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0); + styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10); + } + } -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr; -function gtr(version, range, loose) { - return outside(version, range, '>', loose); + return styles; } -exports.outside = outside; -function outside(version, range, hilo, loose) { - version = new SemVer(version, loose); - range = new Range(range, loose); - - var gtfn, ltefn, ltfn, comp, ecomp; - switch (hilo) { - case '>': - gtfn = gt; - ltefn = lte; - ltfn = lt; - comp = '>'; - ecomp = '>='; - break; - case '<': - gtfn = lt; - ltefn = gte; - ltfn = gt; - comp = '<'; - ecomp = '<='; - break; - default: - throw new TypeError('Must provide a hilo val of "<" or ">"'); - } - - // If it satisifes the range it is not outside - if (satisfies(version, range, loose)) { - return false; - } +// Make the export immutable +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i]; +/***/ }), +/* 152 */ +/***/ (function(module, exports, __webpack_require__) { - var high = null; - var low = null; +"use strict"; - comparators.forEach(function(comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, loose)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, loose)) { - low = comparator; - } - }); +const os = __webpack_require__(11); +const hasFlag = __webpack_require__(12); - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false; - } +const env = process.env; - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false; - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false; - } - } - return true; +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + forceColor = false; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = true; } - -exports.prerelease = prerelease; -function prerelease(version, loose) { - var parsed = parse(version, loose); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; +if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; } -exports.intersects = intersects; -function intersects(r1, r2, loose) { - r1 = new Range(r1, loose) - r2 = new Range(r2, loose) - return r1.intersects(r2) +function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; } -exports.coerce = coerce; -function coerce(version) { - if (version instanceof SemVer) - return version; +function supportsColor(stream) { + if (forceColor === false) { + return 0; + } - if (typeof version !== 'string') - return null; + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } - var match = version.match(re[COERCE]); + if (hasFlag('color=256')) { + return 2; + } - if (match == null) - return null; + if (stream && !stream.isTTY && forceColor !== true) { + // VS code debugger doesn't have isTTY set + if (env.VSCODE_PID) { + return 1; + } + return 0; + } - return parse((match[1] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0')); -} + const min = forceColor ? 1 : 0; + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. 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(process.versions.node.split('.')[0]) >= 8 && + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } -/***/ }), -/* 113 */ -/***/ (function(module, exports, __webpack_require__) { + return 1; + } -"use strict"; + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } + return min; + } -const isWin = process.platform === 'win32'; + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } -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, - }); -} + if (env.COLORTERM === 'truecolor') { + return 3; + } -function hookChildProcess(cp, parsed) { - if (!isWin) { - return; - } + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - const originalEmit = cp.emit; + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } - 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'); + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } - if (err) { - return originalEmit.call(cp, 'error', err); - } - } + if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } - return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params - }; -} + if ('COLORTERM' in env) { + return 1; + } -function verifyENOENT(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawn'); - } + if (env.TERM === 'dumb') { + return min; + } - return null; + return min; } -function verifyENOENTSync(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawnSync'); - } - - return null; +function getSupportLevel(stream) { + const level = supportsColor(stream); + return translateLevel(level); } module.exports = { - hookChildProcess, - verifyENOENT, - verifyENOENTSync, - notFoundError, + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr) }; /***/ }), -/* 114 */ +/* 153 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = function (x) { - var lf = typeof x === 'string' ? '\n' : '\n'.charCodeAt(); - var cr = typeof x === 'string' ? '\r' : '\r'.charCodeAt(); +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; - if (x[x.length - 1] === lf) { - x = x.slice(0, x.length - 1); +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}')`); + } } - if (x[x.length - 1] === cr) { - x = x.slice(0, x.length - 1); - } + return results; +} - return x; -}; +function parseStyle(style) { + STYLE_REGEX.lastIndex = 0; + const results = []; + let matches; -/***/ }), -/* 115 */ -/***/ (function(module, exports, __webpack_require__) { + while ((matches = STYLE_REGEX.exec(style)) !== null) { + const name = matches[1]; -"use strict"; + if (matches[2]) { + const args = parseArguments(name, matches[2]); + results.push([name].concat(args)); + } else { + results.push([name]); + } + } -const path = __webpack_require__(16); -const pathKey = __webpack_require__(116); + return results; +} -module.exports = opts => { - opts = Object.assign({ - cwd: process.cwd(), - path: process.env[pathKey()] - }, opts); +function buildStyle(chalk, styles) { + const enabled = {}; - let prev; - let pth = path.resolve(opts.cwd); - const ret = []; + for (const layer of styles) { + for (const style of layer.styles) { + enabled[style[0]] = layer.inverse ? null : style.slice(1); + } + } - while (prev !== pth) { - ret.push(path.join(pth, 'node_modules/.bin')); - prev = pth; - pth = path.resolve(pth, '..'); + 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]; + } + } } - // ensure the running `node` binary is used - ret.push(path.dirname(process.execPath)); + return current; +} - return ret.concat(opts.path).join(path.delimiter); -}; +module.exports = (chalk, tmp) => { + const styles = []; + const chunks = []; + let chunk = []; -module.exports.env = opts => { - opts = Object.assign({ - env: process.env - }, opts); + // 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'); + } - const env = Object.assign({}, opts.env); - const path = pathKey({env}); + chunks.push(buildStyle(chalk, styles)(chunk.join(''))); + chunk = []; + styles.pop(); + } else { + chunk.push(chr); + } + }); - opts.path = env[path]; - env[path] = module.exports(opts); + chunks.push(chunk.join('')); - return env; + 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(''); }; /***/ }), -/* 116 */ +/* 154 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - -module.exports = opts => { - opts = opts || {}; - - const env = opts.env || process.env; - const platform = opts.platform || process.platform; - - if (platform !== 'win32') { - return 'PATH'; - } +// 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 Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; -}; +module.exports = __webpack_require__(155); +module.exports.cli = __webpack_require__(159); /***/ }), -/* 117 */ +/* 155 */ /***/ (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 -var isStream = module.exports = function (stream) { - return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function'; -}; -isStream.writable = function (stream) { - return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object'; -}; +var stream = __webpack_require__(28); +var util = __webpack_require__(29); +var fs = __webpack_require__(23); -isStream.readable = function (stream) { - return isStream(stream) && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object'; -}; +var through = __webpack_require__(156); +var duplexer = __webpack_require__(157); +var StringDecoder = __webpack_require__(158).StringDecoder; -isStream.duplex = function (stream) { - return isStream.writable(stream) && isStream.readable(stream); -}; +module.exports = Logger; -isStream.transform = function (stream) { - return isStream.duplex(stream) && typeof stream._transform === 'function' && typeof stream._transformState === 'object'; +Logger.DEFAULTS = { + format: 'text', + tag: '', + mergeMultiline: false, + timeStamp: false, }; +var formatters = { + text: textFormatter, + json: jsonFormatter, +} -/***/ }), -/* 118 */ -/***/ (function(module, exports, __webpack_require__) { +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(), + ]; -"use strict"; + if (options.tag) { + transforms.push(staticTagger(options.tag)); + } -const pump = __webpack_require__(119); -const bufferStream = __webpack_require__(121); + if (options.mergeMultiline) { + transforms.push(lineMerger()); + } -class MaxBufferError extends Error { - constructor() { - super('maxBuffer exceeded'); - this.name = 'MaxBufferError'; - } -} + // TODO + // if (options.pidStamp) { + // transforms.push(pidStamper(options.pid)); + // } -function getStream(inputStream, options) { - if (!inputStream) { - return Promise.reject(new Error('Expected a stream')); - } + // TODO + // if (options.workerStamp) { + // transforms.push(workerStamper(options.worker)); + // } - options = Object.assign({maxBuffer: Infinity}, options); + transforms.push(formatters[options.format](options)); - const {maxBuffer} = options; + // restore line endings that were removed by line splitting + transforms.push(reLiner()); - let stream; - return new Promise((resolve, reject) => { - const rejectPromise = error => { - if (error) { // A null check - error.bufferedData = stream.getBufferedValue(); - } - reject(error); - }; + for (var t in transforms) { + emitter = emitter.pipe(transforms[t]); + } - stream = pump(inputStream, bufferStream(options), error => { - if (error) { - rejectPromise(error); - return; - } + return duplexer(catcher, emitter); +} - resolve(); - }); +function deLiner() { + var decoder = new StringDecoder('utf8'); + var last = ''; - stream.on('data', () => { - if (stream.getBufferedLength() > maxBuffer) { - rejectPromise(new MaxBufferError()); - } - }); - }).then(() => stream.getBufferedValue()); + 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(); + }, + }); } -module.exports = getStream; -module.exports.buffer = (stream, options) => getStream(stream, Object.assign({}, options, {encoding: 'buffer'})); -module.exports.array = (stream, options) => getStream(stream, Object.assign({}, options, {array: true})); -module.exports.MaxBufferError = MaxBufferError; +function reLiner() { + return through(appendNewline); + function appendNewline(line) { + this.emit('data', line + '\n'); + } +} -/***/ }), -/* 119 */ -/***/ (function(module, exports, __webpack_require__) { +function objectifier() { + return through(objectify, null, {autoDestroy: false}); -var once = __webpack_require__(51) -var eos = __webpack_require__(120) -var fs = __webpack_require__(23) // we only need fs to get the ReadStream and WriteStream prototypes + function objectify(line) { + this.emit('data', { + msg: line, + time: Date.now(), + }); + } +} -var noop = function () {} -var ancient = /^v?\.0/.test(process.version) +function staticTagger(tag) { + return through(tagger); -var isFn = function (fn) { - return typeof fn === 'function' + function tagger(logEvent) { + logEvent.tag = tag; + this.emit('data', logEvent); + } } -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) -} +function textFormatter(options) { + return through(textify); -var isRequest = function (stream) { - return stream.setHeader && isFn(stream.abort) + 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 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; + } } -var destroyer = function (stream, reading, writing, callback) { - callback = once(callback) +function jsonFormatter(options) { + return through(jsonify); - var closed = false - stream.on('close', function () { - closed = true - }) + 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)); + } +} - eos(stream, {readable: reading, writable: writing}, function (err) { - if (err) return callback(err) - closed = true - callback() - }) +function lineMerger(host) { + var previousLine = null; + var flushTimer = null; + var stream = through(lineMergerWrite, lineMergerEnd); + var flush = _flush.bind(stream); - var destroyed = false - return function (err) { - if (closed) return - if (destroyed) return - destroyed = true + return stream; - 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 + 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); + } - if (isFn(stream.destroy)) return stream.destroy() + function _flush() { + if (previousLine) { + this.emit('data', previousLine); + previousLine = null; + } + } - callback(err || new Error('stream was destroyed')) + function lineMergerEnd() { + flush.call(this); + this.emit('end'); } } -var call = function (fn) { - fn() -} -var pipe = function (from, to) { - return from.pipe(to) -} +/***/ }), +/* 156 */ +/***/ (function(module, exports, __webpack_require__) { -var pump = function () { - var streams = Array.prototype.slice.call(arguments) - var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop +var Stream = __webpack_require__(28) - if (Array.isArray(streams[0])) streams = streams[0] - if (streams.length < 2) throw new Error('pump requires two streams per minimum') +// 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) - 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) - }) - }) +exports = module.exports = through +through.through = through - return streams.reduce(pipe) -} +//create a readable writable stream. -module.exports = pump +function through (write, end, opts) { + write = write || function (data) { this.queue(data) } + end = end || function () { this.queue(null) } + var ended = false, destroyed = false, buffer = [], _ended = false + var stream = new Stream() + stream.readable = stream.writable = true + stream.paused = false -/***/ }), -/* 120 */ -/***/ (function(module, exports, __webpack_require__) { +// stream.autoPause = !(opts && opts.autoPause === false) + stream.autoDestroy = !(opts && opts.autoDestroy === false) -var once = __webpack_require__(51); + stream.write = function (data) { + write.call(this, data) + return !stream.paused + } -var noop = function() {}; + function drain() { + while(buffer.length && !stream.paused) { + var data = buffer.shift() + if(null === data) + return stream.emit('end') + else + stream.emit('data', data) + } + } -var isRequest = function(stream) { - return stream.setHeader && typeof stream.abort === 'function'; -}; + stream.queue = stream.push = function (data) { +// console.error(ended) + if(_ended) return stream + if(data === null) _ended = true + buffer.push(data) + drain() + return stream + } -var isChildProcess = function(stream) { - return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 -}; + //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' -var eos = function(stream, opts, callback) { - if (typeof opts === 'function') return eos(stream, null, opts); - if (!opts) opts = {}; + stream.on('end', function () { + stream.readable = false + if(!stream.writable && stream.autoDestroy) + process.nextTick(function () { + stream.destroy() + }) + }) - callback = once(callback || noop); + function _end () { + stream.writable = false + end.call(stream) + if(!stream.readable && stream.autoDestroy) + stream.destroy() + } - 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); + stream.end = function (data) { + if(ended) return + ended = true + if(arguments.length) stream.write(data) + _end() // will emit or queue + return stream + } - var onlegacyfinish = function() { - if (!stream.writable) onfinish(); - }; + stream.destroy = function () { + if(destroyed) return + destroyed = true + ended = true + buffer.length = 0 + stream.writable = stream.readable = false + stream.emit('close') + return stream + } - var onfinish = function() { - writable = false; - if (!readable) callback.call(stream); - }; + stream.pause = function () { + if(stream.paused) return + stream.paused = true + return stream + } + + 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 +} - var onend = function() { - readable = false; - if (!writable) callback.call(stream); - }; - var onexit = function(exitCode) { - callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); - }; - var onerror = function(err) { - callback.call(stream, err); - }; +/***/ }), +/* 157 */ +/***/ (function(module, exports, __webpack_require__) { - var onclose = function() { - if (readable && !(rs && rs.ended)) return callback.call(stream, new Error('premature close')); - if (writable && !(ws && ws.ended)) return callback.call(stream, new Error('premature close')); - }; +var Stream = __webpack_require__(28) +var writeMethods = ["write", "end", "destroy"] +var readMethods = ["resume", "pause"] +var readEvents = ["data", "close"] +var slice = Array.prototype.slice - var onrequest = function() { - stream.req.on('finish', onfinish); - }; +module.exports = duplex - 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); - } +function forEach (arr, fn) { + if (arr.forEach) { + return arr.forEach(fn) + } - if (isChildProcess(stream)) stream.on('exit', onexit); + for (var i = 0; i < arr.length; i++) { + fn(arr[i], i) + } +} - stream.on('end', onend); - stream.on('finish', onfinish); - if (opts.error !== false) stream.on('error', onerror); - stream.on('close', onclose); +function duplex(writer, reader) { + var stream = new Stream() + var ended = false - return function() { - 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); - }; -}; + forEach(writeMethods, proxyWriter) -module.exports = eos; + forEach(readMethods, proxyReader) + forEach(readEvents, proxyStream) -/***/ }), -/* 121 */ -/***/ (function(module, exports, __webpack_require__) { + reader.on("end", handleEnd) -"use strict"; + writer.on("drain", function() { + stream.emit("drain") + }) -const {PassThrough} = __webpack_require__(28); + writer.on("error", reemit) + reader.on("error", reemit) -module.exports = options => { - options = Object.assign({}, options); + stream.writable = writer.writable + stream.readable = reader.readable - const {array} = options; - let {encoding} = options; - const buffer = encoding === 'buffer'; - let objectMode = false; + return stream - if (array) { - objectMode = !(encoding || buffer); - } else { - encoding = encoding || 'utf8'; - } + function proxyWriter(methodName) { + stream[methodName] = method - if (buffer) { - encoding = null; - } + function method() { + return writer[methodName].apply(writer, arguments) + } + } - let len = 0; - const ret = []; - const stream = new PassThrough({objectMode}); + function proxyReader(methodName) { + stream[methodName] = method - if (encoding) { - stream.setEncoding(encoding); - } + function method() { + stream.emit(methodName) + var func = reader[methodName] + if (func) { + return func.apply(reader, arguments) + } + reader.emit(methodName) + } + } - stream.on('data', chunk => { - ret.push(chunk); + function proxyStream(methodName) { + reader.on(methodName, reemit) - if (objectMode) { - len = ret.length; - } else { - len += chunk.length; - } - }); + function reemit() { + var args = slice.call(arguments) + args.unshift(methodName) + stream.emit.apply(stream, args) + } + } - stream.getBufferedValue = () => { - if (array) { - return ret; - } + function handleEnd() { + if (ended) { + return + } + ended = true + var args = slice.call(arguments) + args.unshift("end") + stream.emit.apply(stream, args) + } - return buffer ? Buffer.concat(ret, len) : ret.join(''); - }; + function reemit(err) { + stream.emit("error", err) + } +} - stream.getBufferedLength = () => len; - return stream; -}; +/***/ }), +/* 158 */ +/***/ (function(module, exports) { +module.exports = require("string_decoder"); /***/ }), -/* 122 */ +/* 159 */ /***/ (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 -module.exports = (promise, onFinally) => { - onFinally = onFinally || (() => {}); - return promise.then( - val => new Promise(resolve => { - resolve(onFinally()); - }).then(() => val), - err => new Promise(resolve => { - resolve(onFinally()); - }).then(() => { - throw err; - }) - ); -}; +var minimist = __webpack_require__(160); +var path = __webpack_require__(16); -/***/ }), -/* 123 */ -/***/ (function(module, exports, __webpack_require__) { +var Logger = __webpack_require__(155); +var pkg = __webpack_require__(161); -"use strict"; +module.exports = cli; -// Older verions of Node.js might not have `util.getSystemErrorName()`. -// In that case, fall back to a deprecated internal. -const util = __webpack_require__(29); +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); + } +} -let uv; +function version($0, p) { + p('%s v%s', pkg.name, pkg.version); +} -if (typeof util.getSystemErrorName === 'function') { - module.exports = util.getSystemErrorName; -} else { - try { - uv = process.binding('uv'); +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(''); - if (typeof uv.errname !== 'function') { - throw new TypeError('uv.errname is not a function'); - } - } catch (err) { - console.error('execa/lib/errname: unable to establish process.binding(\'uv\')', err); - uv = null; - } + function boolOpt(name, def) { + name = name + PADDING.slice(0, 20-name.length); + p(' --%s default: %s', name, def); + } - module.exports = code => errname(uv, code); + function stdOpt(name, def) { + var value = name.toUpperCase() + + PADDING.slice(0, 19 - name.length*2); + p(' --%s %s default: %j', name, value, def); + } } -// Used for testing the fallback behavior -module.exports.__test__ = errname; -function errname(uv, code) { - if (uv) { - return uv.errname(code); - } +/***/ }), +/* 160 */ +/***/ (function(module, exports) { - if (!(code < 0)) { - throw new Error('err >= 0'); - } +module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; - return `Unknown system error ${code}`; -} + 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; + } + }); -/***/ }), -/* 124 */ -/***/ (function(module, exports, __webpack_require__) { + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; -"use strict"; + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } -const alias = ['stdin', 'stdout', 'stderr']; + function argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } -const hasAlias = opts => alias.some(x => Boolean(opts[x])); + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } -module.exports = opts => { - if (!opts) { - return null; - } + 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); + }); + } - if (opts.stdio && hasAlias(opts)) { - throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${alias.map(x => `\`${x}\``).join(', ')}`); - } + function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); - if (typeof opts.stdio === 'string') { - return opts.stdio; - } + var key = keys[keys.length - 1]; + 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 stdio = opts.stdio || []; + 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); + }); + } - if (!Array.isArray(stdio)) { - throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); - } + return argv; +}; - const result = []; - const len = Math.max(stdio.length, alias.length); +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); - for (let i = 0; i < len; i++) { - let value = null; + var key = keys[keys.length - 1]; + return key in o; +} + +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); +} - if (stdio[i] !== undefined) { - value = stdio[i]; - } else if (opts[alias[i]] !== undefined) { - value = opts[alias[i]]; - } - result[i] = value; - } - return result; -}; +/***/ }), +/* 161 */ +/***/ (function(module) { +module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); /***/ }), -/* 125 */ -/***/ (function(module, exports, __webpack_require__) { +/* 162 */ +/***/ (function(module, __webpack_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__(37); +/* 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__(16); +/* 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__(29); +/* 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__(163); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(55); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(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. + */ -const chalk = __webpack_require__(2); - -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; -/***/ }), -/* 126 */ -/***/ (function(module, exports, __webpack_require__) { -// 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 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); -module.exports = __webpack_require__(127); -module.exports.cli = __webpack_require__(131); + if (!rootPkgJson.workspaces) { + return []; + } + const workspacesPathsPatterns = rootPkgJson.workspaces.packages; + let workspaceProjectsPaths = []; -/***/ }), -/* 127 */ -/***/ (function(module, exports, __webpack_require__) { + for (const pattern of workspacesPathsPatterns) { + workspaceProjectsPaths = workspaceProjectsPaths.concat((await packagesFromGlobPattern({ + pattern, + rootPath + }))); + } // Filter out exclude glob patterns -"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 + 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); + } + } + 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); -var stream = __webpack_require__(28); -var util = __webpack_require__(29); -var fs = __webpack_require__(23); + for (const project of projects.values()) { + const dest = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(rootPath, 'node_modules', project.name); -var through = __webpack_require__(128); -var duplexer = __webpack_require__(129); -var StringDecoder = __webpack_require__(130).StringDecoder; + if ((await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["isSymlink"])(dest)) === false) { + continue; + } // Remove the symlink -module.exports = Logger; -Logger.DEFAULTS = { - format: 'text', - tag: '', - mergeMultiline: false, - timeStamp: false, -}; + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["unlink"])(dest); // Copy in the package -var formatters = { - text: textFormatter, - json: jsonFormatter, + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["copyDirectory"])(project.path, dest); + } } -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(), - ]; +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); +} - if (options.tag) { - transforms.push(staticTagger(options.tag)); - } +/***/ }), +/* 163 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - if (options.mergeMultiline) { - transforms.push(lineMerger()); - } +"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__(16); +/* 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. + */ - // TODO - // if (options.pidStamp) { - // transforms.push(pidStamper(options.pid)); - // } - // TODO - // if (options.workerStamp) { - // transforms.push(workerStamper(options.worker)); - // } +/** + * Returns all the paths where plugins are located + */ +function getProjectPaths(rootPath, options = {}) { + const skipKibanaPlugins = Boolean(options['skip-kibana-plugins']); + const ossOnly = Boolean(options.oss); + 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. - transforms.push(formatters[options.format](options)); + 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/*')); - // restore line endings that were removed by line splitting - transforms.push(reLiner()); + 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/legacy/plugins/*')); + } - for (var t in transforms) { - emitter = emitter.pipe(transforms[t]); + 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/*')); } - return duplexer(catcher, emitter); + return projectPaths; } -function deLiner() { - var decoder = new StringDecoder('utf8'); - var last = ''; +/***/ }), +/* 164 */ +/***/ (function(module, __webpack_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"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(180); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(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. + */ -function reLiner() { - return through(appendNewline); - function appendNewline(line) { - this.emit('data', line + '\n'); - } -} -function objectifier() { - return through(objectify, null, {autoDestroy: false}); - function objectify(line) { - this.emit('data', { - msg: line, - time: Date.now(), - }); - } -} -function staticTagger(tag) { - return through(tagger); - function tagger(logEvent) { - logEvent.tag = tag; - this.emit('data', logEvent); - } -} +const CleanCommand = { + description: 'Remove the node_modules and target directories from all projects.', + name: 'clean', -function textFormatter(options) { - return through(textify); + async run(projects) { + const toDelete = []; - 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')); - } + for (const project of projects.values()) { + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.nodeModulesLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.nodeModulesLocation) + }); + } - 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] + ' '; + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.targetLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.targetLocation) + }); } - } - return str; - } -} -function jsonFormatter(options) { - return through(jsonify); + const { + extraPatterns + } = project.getCleanConfig(); - function jsonify(logEvent) { - if (options.timeStamp) { - logEvent.time = new Date(logEvent.time).toISOString(); - } else { - delete logEvent.time; + if (extraPatterns) { + toDelete.push({ + cwd: project.path, + pattern: extraPatterns + }); + } } - 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); + if (toDelete.length === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.green('\n\nNothing to delete')); + } else { + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.red('\n\nDeleting:\n')); + /** + * 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. + */ - return stream; + const originalCwd = process.cwd(); - function lineMergerWrite(line) { - if (/^\s+/.test(line.msg)) { - if (previousLine) { - previousLine.msg += '\n' + line.msg; - } else { - previousLine = line; + try { + for (const _ref of toDelete) { + const { + pattern, + cwd + } = _ref; + process.chdir(cwd); + const promise = del__WEBPACK_IMPORTED_MODULE_1___default()(pattern); + ora__WEBPACK_IMPORTED_MODULE_2___default.a.promise(promise, Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(originalCwd, Object(path__WEBPACK_IMPORTED_MODULE_3__["join"])(cwd, String(pattern)))); + await promise; + } + } finally { + process.chdir(originalCwd); } - } else { - flush(); - previousLine = line; - } - // rolling timeout - clearTimeout(flushTimer); - flushTimer = setTimeout(flush.bind(this), 10); - } - - function _flush() { - if (previousLine) { - this.emit('data', previousLine); - previousLine = null; } } - function lineMergerEnd() { - flush.call(this); - this.emit('end'); - } -} - +}; /***/ }), -/* 128 */ +/* 165 */ /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__(28) - -// 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) +"use strict"; -exports = module.exports = through -through.through = through +const path = __webpack_require__(16); +const globby = __webpack_require__(166); +const isPathCwd = __webpack_require__(173); +const isPathInCwd = __webpack_require__(174); +const pify = __webpack_require__(177); +const rimraf = __webpack_require__(178); +const pMap = __webpack_require__(179); -//create a readable writable stream. +const rimrafP = pify(rimraf); -function through (write, end, opts) { - write = write || function (data) { this.queue(data) } - end = end || function () { this.queue(null) } +function safeCheck(file) { + if (isPathCwd(file)) { + throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.'); + } - var ended = false, destroyed = false, buffer = [], _ended = false - var stream = new Stream() - stream.readable = stream.writable = true - stream.paused = false + if (!isPathInCwd(file)) { + throw new Error('Cannot delete files/folders outside the current working directory. Can be overridden with the `force` option.'); + } +} -// stream.autoPause = !(opts && opts.autoPause === false) - stream.autoDestroy = !(opts && opts.autoDestroy === false) +const del = (patterns, options) => { + options = Object.assign({}, options); - stream.write = function (data) { - write.call(this, data) - return !stream.paused - } + const {force, dryRun} = options; + delete options.force; + delete options.dryRun; - function drain() { - while(buffer.length && !stream.paused) { - var data = buffer.shift() - if(null === data) - return stream.emit('end') - else - stream.emit('data', data) - } - } + const mapper = file => { + if (!force) { + safeCheck(file); + } - stream.queue = stream.push = function (data) { -// console.error(ended) - if(_ended) return stream - if(data === null) _ended = true - buffer.push(data) - drain() - return stream - } + file = path.resolve(options.cwd || '', file); - //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' + if (dryRun) { + return file; + } - stream.on('end', function () { - stream.readable = false - if(!stream.writable && stream.autoDestroy) - process.nextTick(function () { - stream.destroy() - }) - }) + return rimrafP(file, {glob: false}).then(() => file); + }; - function _end () { - stream.writable = false - end.call(stream) - if(!stream.readable && stream.autoDestroy) - stream.destroy() - } + return globby(patterns, options).then(files => pMap(files, mapper, options)); +}; - stream.end = function (data) { - if(ended) return - ended = true - if(arguments.length) stream.write(data) - _end() // will emit or queue - return stream - } +module.exports = del; +// TODO: Remove this for the next major release +module.exports.default = del; - stream.destroy = function () { - if(destroyed) return - destroyed = true - ended = true - buffer.length = 0 - stream.writable = stream.readable = false - stream.emit('close') - return stream - } +module.exports.sync = (patterns, options) => { + options = Object.assign({}, options); - stream.pause = function () { - if(stream.paused) return - stream.paused = true - return stream - } + const {force, dryRun} = options; + delete options.force; + delete options.dryRun; - 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 globby.sync(patterns, options).map(file => { + if (!force) { + safeCheck(file); + } + + file = path.resolve(options.cwd || '', file); + + if (!dryRun) { + rimraf.sync(file, {glob: false}); + } + return file; + }); +}; /***/ }), -/* 129 */ +/* 166 */ /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__(28) -var writeMethods = ["write", "end", "destroy"] -var readMethods = ["resume", "pause"] -var readEvents = ["data", "close"] -var slice = Array.prototype.slice +"use strict"; -module.exports = duplex +var Promise = __webpack_require__(167); +var arrayUnion = __webpack_require__(169); +var objectAssign = __webpack_require__(171); +var glob = __webpack_require__(37); +var pify = __webpack_require__(172); -function forEach (arr, fn) { - if (arr.forEach) { - return arr.forEach(fn) - } +var globP = pify(glob, Promise).bind(glob); - for (var i = 0; i < arr.length; i++) { - fn(arr[i], i) - } +function isNegative(pattern) { + return pattern[0] === '!'; } -function duplex(writer, reader) { - var stream = new Stream() - var ended = false - - forEach(writeMethods, proxyWriter) - - forEach(readMethods, proxyReader) - - forEach(readEvents, proxyStream) +function isString(value) { + return typeof value === 'string'; +} - reader.on("end", handleEnd) +function assertPatternsInput(patterns) { + if (!patterns.every(isString)) { + throw new TypeError('patterns must be a string or an array of strings'); + } +} - writer.on("drain", function() { - stream.emit("drain") - }) +function generateGlobTasks(patterns, opts) { + patterns = [].concat(patterns); + assertPatternsInput(patterns); - writer.on("error", reemit) - reader.on("error", reemit) + var globTasks = []; - stream.writable = writer.writable - stream.readable = reader.readable + opts = objectAssign({ + cache: Object.create(null), + statCache: Object.create(null), + realpathCache: Object.create(null), + symlinks: Object.create(null), + ignore: [] + }, opts); - return stream + patterns.forEach(function (pattern, i) { + if (isNegative(pattern)) { + return; + } - function proxyWriter(methodName) { - stream[methodName] = method + var ignore = patterns.slice(i).filter(isNegative).map(function (pattern) { + return pattern.slice(1); + }); - function method() { - return writer[methodName].apply(writer, arguments) - } - } + globTasks.push({ + pattern: pattern, + opts: objectAssign({}, opts, { + ignore: opts.ignore.concat(ignore) + }) + }); + }); - function proxyReader(methodName) { - stream[methodName] = method + return globTasks; +} - function method() { - stream.emit(methodName) - var func = reader[methodName] - if (func) { - return func.apply(reader, arguments) - } - reader.emit(methodName) - } - } +module.exports = function (patterns, opts) { + var globTasks; - function proxyStream(methodName) { - reader.on(methodName, reemit) + try { + globTasks = generateGlobTasks(patterns, opts); + } catch (err) { + return Promise.reject(err); + } - function reemit() { - var args = slice.call(arguments) - args.unshift(methodName) - stream.emit.apply(stream, args) - } - } + return Promise.all(globTasks.map(function (task) { + return globP(task.pattern, task.opts); + })).then(function (paths) { + return arrayUnion.apply(null, paths); + }); +}; - function handleEnd() { - if (ended) { - return - } - ended = true - var args = slice.call(arguments) - args.unshift("end") - stream.emit.apply(stream, args) - } +module.exports.sync = function (patterns, opts) { + var globTasks = generateGlobTasks(patterns, opts); - function reemit(err) { - stream.emit("error", err) - } -} + return globTasks.reduce(function (matches, task) { + return arrayUnion(matches, glob.sync(task.pattern, task.opts)); + }, []); +}; +module.exports.generateGlobTasks = generateGlobTasks; -/***/ }), -/* 130 */ -/***/ (function(module, exports) { +module.exports.hasMagic = function (patterns, opts) { + return [].concat(patterns).some(function (pattern) { + return glob.hasMagic(pattern, opts); + }); +}; -module.exports = require("string_decoder"); /***/ }), -/* 131 */ +/* 167 */ /***/ (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 +module.exports = typeof Promise === 'function' ? Promise : __webpack_require__(168); -var minimist = __webpack_require__(132); -var path = __webpack_require__(16); -var Logger = __webpack_require__(127); -var pkg = __webpack_require__(133); +/***/ }), +/* 168 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = cli; +"use strict"; -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); - } -} -function version($0, p) { - p('%s v%s', pkg.name, pkg.version); -} +var PENDING = 'pending'; +var SETTLED = 'settled'; +var FULFILLED = 'fulfilled'; +var REJECTED = 'rejected'; +var NOOP = function () {}; +var isNode = typeof global !== 'undefined' && typeof global.process !== 'undefined' && typeof global.process.emit === 'function'; -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(''); +var asyncSetTimer = typeof setImmediate === 'undefined' ? setTimeout : setImmediate; +var asyncQueue = []; +var asyncTimer; - function boolOpt(name, def) { - name = name + PADDING.slice(0, 20-name.length); - p(' --%s default: %s', name, def); - } +function asyncFlush() { + // run promise callbacks + for (var i = 0; i < asyncQueue.length; i++) { + asyncQueue[i][0](asyncQueue[i][1]); + } - function stdOpt(name, def) { - var value = name.toUpperCase() + - PADDING.slice(0, 19 - name.length*2); - p(' --%s %s default: %j', name, value, def); - } + // reset async asyncQueue + asyncQueue = []; + asyncTimer = false; } +function asyncCall(callback, arg) { + asyncQueue.push([callback, arg]); -/***/ }), -/* 132 */ -/***/ (function(module, exports) { - -module.exports = function (args, opts) { - if (!opts) opts = {}; - - var flags = { bools : {}, strings : {}, unknownFn: null }; - - 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; - })); - }); - }); + if (!asyncTimer) { + asyncTimer = true; + asyncSetTimer(asyncFlush, 0); + } +} - [].concat(opts.string).filter(Boolean).forEach(function (key) { - flags.strings[key] = true; - if (aliases[key]) { - flags.strings[aliases[key]] = true; - } - }); +function invokeResolver(resolver, promise) { + function resolvePromise(value) { + resolve(promise, value); + } - var defaults = opts['default'] || {}; - - var argv = { _ : [] }; - Object.keys(flags.bools).forEach(function (key) { - setArg(key, defaults[key] === undefined ? false : defaults[key]); - }); - - var notFlags = []; + function rejectPromise(reason) { + reject(promise, reason); + } - if (args.indexOf('--') !== -1) { - notFlags = args.slice(args.indexOf('--')+1); - args = args.slice(0, args.indexOf('--')); - } + try { + resolver(resolvePromise, rejectPromise); + } catch (e) { + rejectPromise(e); + } +} - function argDefined(key, arg) { - return (flags.allBools && /^--[^=]+$/.test(arg)) || - flags.strings[key] || flags.bools[key] || aliases[key]; - } +function invokeCallback(subscriber) { + var owner = subscriber.owner; + var settled = owner._state; + var value = owner._data; + var callback = subscriber[settled]; + var promise = subscriber.then; - function setArg (key, val, arg) { - if (arg && flags.unknownFn && !argDefined(key, arg)) { - if (flags.unknownFn(arg) === false) return; - } + if (typeof callback === 'function') { + settled = FULFILLED; + try { + value = callback(value); + } catch (e) { + reject(promise, e); + } + } - 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); - }); - } + if (!handleThenable(promise, value)) { + if (settled === FULFILLED) { + resolve(promise, value); + } - function setKey (obj, keys, value) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - if (o[key] === undefined) o[key] = {}; - o = o[key]; - }); + if (settled === REJECTED) { + reject(promise, value); + } + } +} - var key = keys[keys.length - 1]; - 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]; - }); - } +function handleThenable(promise, value) { + var resolved; - 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); - }); - } + try { + if (promise === value) { + throw new TypeError('A promises callback cannot return that same promise.'); + } - return argv; -}; + if (value && (typeof value === 'function' || typeof value === 'object')) { + // then should be retrieved only once + var then = value.then; -function hasKey (obj, keys) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - o = (o[key] || {}); - }); + if (typeof then === 'function') { + then.call(value, function (val) { + if (!resolved) { + resolved = true; - var key = keys[keys.length - 1]; - return key in o; + if (value === val) { + fulfill(promise, val); + } else { + resolve(promise, val); + } + } + }, function (reason) { + if (!resolved) { + resolved = true; + + reject(promise, reason); + } + }); + + return true; + } + } + } catch (e) { + if (!resolved) { + reject(promise, e); + } + + return true; + } + + return false; } -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); +function resolve(promise, value) { + if (promise === value || !handleThenable(promise, value)) { + fulfill(promise, value); + } } +function fulfill(promise, value) { + if (promise._state === PENDING) { + promise._state = SETTLED; + promise._data = value; + asyncCall(publishFulfillment, promise); + } +} -/***/ }), -/* 133 */ -/***/ (function(module) { +function reject(promise, reason) { + if (promise._state === PENDING) { + promise._state = SETTLED; + promise._data = reason; -module.exports = {"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"}}; + asyncCall(publishRejection, promise); + } +} -/***/ }), -/* 134 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +function publish(promise) { + promise._then = promise._then.forEach(invokeCallback); +} -"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__(36); -/* 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__(16); -/* 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__(29); -/* 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__(135); -/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(54); -/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(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. +function publishFulfillment(promise) { + promise._state = FULFILLED; + publish(promise); +} + +function publishRejection(promise) { + promise._state = REJECTED; + publish(promise); + if (!promise._handled && isNode) { + global.process.emit('unhandledRejection', promise._data, promise); + } +} + +function notifyRejectionHandled(promise) { + global.process.emit('rejectionHandled', promise); +} + +/** + * @class */ +function Promise(resolver) { + if (typeof resolver !== 'function') { + throw new TypeError('Promise resolver ' + resolver + ' is not a function'); + } + if (this instanceof Promise === false) { + throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.'); + } + this._then = []; + invokeResolver(resolver, this); +} +Promise.prototype = { + constructor: Promise, + _state: PENDING, + _then: null, + _data: undefined, + _handled: false, + then: function (onFulfillment, onRejection) { + var subscriber = { + owner: this, + then: new this.constructor(NOOP), + fulfilled: onFulfillment, + rejected: onRejection + }; -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"])(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(rootPath, 'package.json')); + if ((onRejection || onFulfillment) && !this._handled) { + this._handled = true; + if (this._state === REJECTED && isNode) { + asyncCall(notifyRejectionHandled, this); + } + } - if (!rootPkgJson.workspaces) { - return []; - } + if (this._state === FULFILLED || this._state === REJECTED) { + // already resolved, call callback async + asyncCall(invokeCallback, subscriber); + } else { + // subscribe + this._then.push(subscriber); + } - const workspacesPathsPatterns = rootPkgJson.workspaces.packages; - let workspaceProjectsPaths = []; + return subscriber.then; + }, - for (const pattern of workspacesPathsPatterns) { - workspaceProjectsPaths = workspaceProjectsPaths.concat((await packagesFromGlobPattern({ - pattern, - rootPath - }))); - } // Filter out exclude glob patterns + catch: function (onRejection) { + return this.then(null, onRejection); + } +}; +Promise.all = function (promises) { + if (!Array.isArray(promises)) { + throw new TypeError('You must pass an array to Promise.all().'); + } - 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); - } - } + return new Promise(function (resolve, reject) { + var results = []; + var remaining = 0; - 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); + function resolver(index) { + remaining++; + return function (value) { + results[index] = value; + if (!--remaining) { + resolve(results); + } + }; + } - for (const project of projects.values()) { - const dest = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(rootPath, 'node_modules', project.name); + for (var i = 0, promise; i < promises.length; i++) { + promise = promises[i]; - if ((await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["isSymlink"])(dest)) === false) { - continue; - } // Remove the symlink + if (promise && typeof promise.then === 'function') { + promise.then(resolver(i), reject); + } else { + results[i] = promise; + } + } + if (!remaining) { + resolve(results); + } + }); +}; - await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["unlink"])(dest); // Copy in the package +Promise.race = function (promises) { + if (!Array.isArray(promises)) { + throw new TypeError('You must pass an array to Promise.race().'); + } - await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["copyDirectory"])(project.path, dest); - } -} + return new Promise(function (resolve, reject) { + for (var i = 0, promise; i < promises.length; i++) { + promise = promises[i]; -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); -} + if (promise && typeof promise.then === 'function') { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + }); +}; -/***/ }), -/* 135 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +Promise.resolve = function (value) { + if (value && typeof value === 'object' && value.constructor === Promise) { + return value; + } -"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__(16); -/* 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. - */ + return new Promise(function (resolve) { + resolve(value); + }); +}; +Promise.reject = function (reason) { + return new Promise(function (resolve, reject) { + reject(reason); + }); +}; -/** - * Returns all the paths where plugins are located - */ -function getProjectPaths(rootPath, options = {}) { - const skipKibanaPlugins = Boolean(options['skip-kibana-plugins']); - const ossOnly = Boolean(options.oss); - 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. +module.exports = Promise; - 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/*')); - 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/legacy/plugins/*')); - } +/***/ }), +/* 169 */ +/***/ (function(module, exports, __webpack_require__) { - 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/*')); - } +"use strict"; + +var arrayUniq = __webpack_require__(170); + +module.exports = function () { + return arrayUniq([].concat.apply([], arguments)); +}; - return projectPaths; -} /***/ }), -/* 136 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/* 170 */ +/***/ (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 chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(137); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(152); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(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. - */ +// there's 3 implementations written in increasing order of efficiency +// 1 - no Set type is defined +function uniqNoSet(arr) { + var ret = []; + for (var i = 0; i < arr.length; i++) { + if (ret.indexOf(arr[i]) === -1) { + ret.push(arr[i]); + } + } + return ret; +} -const CleanCommand = { - description: 'Remove the node_modules and target directories from all projects.', - name: 'clean', +// 2 - a simple Set type is defined +function uniqSet(arr) { + var seen = new Set(); + return arr.filter(function (el) { + if (!seen.has(el)) { + seen.add(el); + return true; + } - async run(projects) { - const toDelete = []; + return false; + }); +} - for (const project of projects.values()) { - if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.nodeModulesLocation)) { - toDelete.push({ - cwd: project.path, - pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.nodeModulesLocation) - }); - } +// 3 - a standard Set type is defined and it has a forEach method +function uniqSetWithForEach(arr) { + var ret = []; - if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(project.targetLocation)) { - toDelete.push({ - cwd: project.path, - pattern: Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(project.path, project.targetLocation) - }); - } + (new Set(arr)).forEach(function (el) { + ret.push(el); + }); - const { - extraPatterns - } = project.getCleanConfig(); + return ret; +} - if (extraPatterns) { - toDelete.push({ - cwd: project.path, - pattern: extraPatterns - }); - } - } +// V8 currently has a broken implementation +// https://github.com/joyent/node/issues/8449 +function doesForEachActuallyWork() { + var ret = false; - if (toDelete.length === 0) { - _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.green('\n\nNothing to delete')); - } else { - _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].write(chalk__WEBPACK_IMPORTED_MODULE_0___default.a.bold.red('\n\nDeleting:\n')); - /** - * 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. - */ + (new Set([true])).forEach(function (el) { + ret = el; + }); - const originalCwd = process.cwd(); + return ret === true; +} - try { - for (const _ref of toDelete) { - const { - pattern, - cwd - } = _ref; - process.chdir(cwd); - const promise = del__WEBPACK_IMPORTED_MODULE_1___default()(pattern); - ora__WEBPACK_IMPORTED_MODULE_2___default.a.promise(promise, Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(originalCwd, Object(path__WEBPACK_IMPORTED_MODULE_3__["join"])(cwd, String(pattern)))); - await promise; - } - } finally { - process.chdir(originalCwd); - } - } - } +if ('Set' in global) { + if (typeof Set.prototype.forEach === 'function' && doesForEachActuallyWork()) { + module.exports = uniqSetWithForEach; + } else { + module.exports = uniqSet; + } +} else { + module.exports = uniqNoSet; +} -}; /***/ }), -/* 137 */ +/* 171 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ -const path = __webpack_require__(16); -const globby = __webpack_require__(138); -const isPathCwd = __webpack_require__(145); -const isPathInCwd = __webpack_require__(146); -const pify = __webpack_require__(149); -const rimraf = __webpack_require__(150); -const pMap = __webpack_require__(151); -const rimrafP = pify(rimraf); +/* eslint-disable no-unused-vars */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; -function safeCheck(file) { - if (isPathCwd(file)) { - throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.'); +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); } - if (!isPathInCwd(file)) { - throw new Error('Cannot delete files/folders outside the current working directory. Can be overridden with the `force` option.'); - } + return Object(val); } -const del = (patterns, options) => { - options = Object.assign({}, options); - - const {force, dryRun} = options; - delete options.force; - delete options.dryRun; - - const mapper = file => { - if (!force) { - safeCheck(file); +function shouldUseNative() { + try { + if (!Object.assign) { + return false; } - file = path.resolve(options.cwd || '', file); + // Detect buggy property enumeration order in older V8 versions. - if (dryRun) { - return file; + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; } - return rimrafP(file, {glob: false}).then(() => file); - }; + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } - return globby(patterns, options).then(files => pMap(files, mapper, options)); -}; + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } -module.exports = del; -// TODO: Remove this for the next major release -module.exports.default = del; + return true; + } catch (err) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} -module.exports.sync = (patterns, options) => { - options = Object.assign({}, options); +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; - const {force, dryRun} = options; - delete options.force; - delete options.dryRun; + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); - return globby.sync(patterns, options).map(file => { - if (!force) { - safeCheck(file); + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } } - file = path.resolve(options.cwd || '', file); - - if (!dryRun) { - rimraf.sync(file, {glob: false}); + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } } + } - return file; - }); + return to; }; /***/ }), -/* 138 */ +/* 172 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Promise = __webpack_require__(139); -var arrayUnion = __webpack_require__(141); -var objectAssign = __webpack_require__(143); -var glob = __webpack_require__(36); -var pify = __webpack_require__(144); -var globP = pify(glob, Promise).bind(glob); +var processFn = function (fn, P, opts) { + return function () { + var that = this; + var args = new Array(arguments.length); -function isNegative(pattern) { - return pattern[0] === '!'; -} + for (var i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } -function isString(value) { - return typeof value === 'string'; -} + return new P(function (resolve, reject) { + args.push(function (err, result) { + if (err) { + reject(err); + } else if (opts.multiArgs) { + var results = new Array(arguments.length - 1); -function assertPatternsInput(patterns) { - if (!patterns.every(isString)) { - throw new TypeError('patterns must be a string or an array of strings'); + for (var i = 1; i < arguments.length; i++) { + results[i - 1] = arguments[i]; + } + + resolve(results); + } else { + resolve(result); + } + }); + + fn.apply(that, args); + }); + }; +}; + +var pify = module.exports = function (obj, P, opts) { + if (typeof P !== 'function') { + opts = P; + P = Promise; } -} -function generateGlobTasks(patterns, opts) { - patterns = [].concat(patterns); - assertPatternsInput(patterns); + opts = opts || {}; + opts.exclude = opts.exclude || [/.+Sync$/]; - var globTasks = []; + var filter = function (key) { + var match = function (pattern) { + return typeof pattern === 'string' ? key === pattern : pattern.test(key); + }; - opts = objectAssign({ - cache: Object.create(null), - statCache: Object.create(null), - realpathCache: Object.create(null), - symlinks: Object.create(null), - ignore: [] - }, opts); + return opts.include ? opts.include.some(match) : !opts.exclude.some(match); + }; - patterns.forEach(function (pattern, i) { - if (isNegative(pattern)) { - return; + var ret = typeof obj === 'function' ? function () { + if (opts.excludeMain) { + return obj.apply(this, arguments); } - var ignore = patterns.slice(i).filter(isNegative).map(function (pattern) { - return pattern.slice(1); - }); + return processFn(obj, P, opts).apply(this, arguments); + } : {}; - globTasks.push({ - pattern: pattern, - opts: objectAssign({}, opts, { - ignore: opts.ignore.concat(ignore) - }) - }); - }); + return Object.keys(obj).reduce(function (ret, key) { + var x = obj[key]; - return globTasks; -} + ret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x; -module.exports = function (patterns, opts) { - var globTasks; + return ret; + }, ret); +}; - try { - globTasks = generateGlobTasks(patterns, opts); - } catch (err) { - return Promise.reject(err); - } +pify.all = pify; - return Promise.all(globTasks.map(function (task) { - return globP(task.pattern, task.opts); - })).then(function (paths) { - return arrayUnion.apply(null, paths); - }); -}; -module.exports.sync = function (patterns, opts) { - var globTasks = generateGlobTasks(patterns, opts); +/***/ }), +/* 173 */ +/***/ (function(module, exports, __webpack_require__) { - return globTasks.reduce(function (matches, task) { - return arrayUnion(matches, glob.sync(task.pattern, task.opts)); - }, []); -}; +"use strict"; -module.exports.generateGlobTasks = generateGlobTasks; +const path = __webpack_require__(16); -module.exports.hasMagic = function (patterns, opts) { - return [].concat(patterns).some(function (pattern) { - return glob.hasMagic(pattern, opts); - }); -}; +module.exports = path_ => path.resolve(path_) === process.cwd(); /***/ }), -/* 139 */ +/* 174 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const isPathInside = __webpack_require__(175); -module.exports = typeof Promise === 'function' ? Promise : __webpack_require__(140); +module.exports = path => isPathInside(path, process.cwd()); /***/ }), -/* 140 */ +/* 175 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const path = __webpack_require__(16); +const pathIsInside = __webpack_require__(176); -var PENDING = 'pending'; -var SETTLED = 'settled'; -var FULFILLED = 'fulfilled'; -var REJECTED = 'rejected'; -var NOOP = function () {}; -var isNode = typeof global !== 'undefined' && typeof global.process !== 'undefined' && typeof global.process.emit === 'function'; - -var asyncSetTimer = typeof setImmediate === 'undefined' ? setTimeout : setImmediate; -var asyncQueue = []; -var asyncTimer; +module.exports = (childPath, parentPath) => { + childPath = path.resolve(childPath); + parentPath = path.resolve(parentPath); -function asyncFlush() { - // run promise callbacks - for (var i = 0; i < asyncQueue.length; i++) { - asyncQueue[i][0](asyncQueue[i][1]); + if (childPath === parentPath) { + return false; } - // reset async asyncQueue - asyncQueue = []; - asyncTimer = false; -} + return pathIsInside(childPath, parentPath); +}; -function asyncCall(callback, arg) { - asyncQueue.push([callback, arg]); - if (!asyncTimer) { - asyncTimer = true; - asyncSetTimer(asyncFlush, 0); - } -} +/***/ }), +/* 176 */ +/***/ (function(module, exports, __webpack_require__) { -function invokeResolver(resolver, promise) { - function resolvePromise(value) { - resolve(promise, value); - } +"use strict"; - function rejectPromise(reason) { - reject(promise, reason); - } - try { - resolver(resolvePromise, rejectPromise); - } catch (e) { - rejectPromise(e); - } -} +var path = __webpack_require__(16); -function invokeCallback(subscriber) { - var owner = subscriber.owner; - var settled = owner._state; - var value = owner._data; - var callback = subscriber[settled]; - var promise = subscriber.then; +module.exports = function (thePath, potentialParent) { + // For inside-directory checking, we want to allow trailing slashes, so normalize. + thePath = stripTrailingSep(thePath); + potentialParent = stripTrailingSep(potentialParent); - if (typeof callback === 'function') { - settled = FULFILLED; - try { - value = callback(value); - } catch (e) { - reject(promise, e); - } - } + // Node treats only Windows as case-insensitive in its path module; we follow those conventions. + if (process.platform === "win32") { + thePath = thePath.toLowerCase(); + potentialParent = potentialParent.toLowerCase(); + } - if (!handleThenable(promise, value)) { - if (settled === FULFILLED) { - resolve(promise, value); - } + return thePath.lastIndexOf(potentialParent, 0) === 0 && + ( + thePath[potentialParent.length] === path.sep || + thePath[potentialParent.length] === undefined + ); +}; - if (settled === REJECTED) { - reject(promise, value); - } - } +function stripTrailingSep(thePath) { + if (thePath[thePath.length - 1] === path.sep) { + return thePath.slice(0, -1); + } + return thePath; } -function handleThenable(promise, value) { - var resolved; - try { - if (promise === value) { - throw new TypeError('A promises callback cannot return that same promise.'); - } +/***/ }), +/* 177 */ +/***/ (function(module, exports, __webpack_require__) { - if (value && (typeof value === 'function' || typeof value === 'object')) { - // then should be retrieved only once - var then = value.then; +"use strict"; - if (typeof then === 'function') { - then.call(value, function (val) { - if (!resolved) { - resolved = true; - if (value === val) { - fulfill(promise, val); - } else { - resolve(promise, val); - } - } - }, function (reason) { - if (!resolved) { - resolved = true; +const processFn = (fn, options) => function (...args) { + const P = options.promiseModule; - reject(promise, reason); + return new P((resolve, reject) => { + if (options.multiArgs) { + args.push((...result) => { + if (options.errorFirst) { + if (result[0]) { + reject(result); + } else { + result.shift(); + resolve(result); } - }); - - return true; - } - } - } catch (e) { - if (!resolved) { - reject(promise, e); + } else { + resolve(result); + } + }); + } else if (options.errorFirst) { + args.push((error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); + } else { + args.push(resolve); } - return true; - } + fn.apply(this, args); + }); +}; - return false; -} +module.exports = (input, options) => { + options = Object.assign({ + exclude: [/.+(Sync|Stream)$/], + errorFirst: true, + promiseModule: Promise + }, options); -function resolve(promise, value) { - if (promise === value || !handleThenable(promise, value)) { - fulfill(promise, value); + const objType = typeof input; + if (!(input !== null && (objType === 'object' || objType === 'function'))) { + throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); } -} -function fulfill(promise, value) { - if (promise._state === PENDING) { - promise._state = SETTLED; - promise._data = value; + const filter = key => { + const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); + return options.include ? options.include.some(match) : !options.exclude.some(match); + }; - asyncCall(publishFulfillment, promise); + let ret; + if (objType === 'function') { + ret = function (...args) { + return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); + }; + } else { + ret = Object.create(Object.getPrototypeOf(input)); } -} - -function reject(promise, reason) { - if (promise._state === PENDING) { - promise._state = SETTLED; - promise._data = reason; - asyncCall(publishRejection, promise); + for (const key in input) { // eslint-disable-line guard-for-in + const property = input[key]; + ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; } -} -function publish(promise) { - promise._then = promise._then.forEach(invokeCallback); -} + return ret; +}; -function publishFulfillment(promise) { - promise._state = FULFILLED; - publish(promise); -} -function publishRejection(promise) { - promise._state = REJECTED; - publish(promise); - if (!promise._handled && isNode) { - global.process.emit('unhandledRejection', promise._data, promise); - } -} +/***/ }), +/* 178 */ +/***/ (function(module, exports, __webpack_require__) { -function notifyRejectionHandled(promise) { - global.process.emit('rejectionHandled', promise); +module.exports = rimraf +rimraf.sync = rimrafSync + +var assert = __webpack_require__(30) +var path = __webpack_require__(16) +var fs = __webpack_require__(23) +var glob = __webpack_require__(37) +var _0666 = parseInt('666', 8) + +var defaultGlobOpts = { + nosort: true, + silent: true } -/** - * @class - */ -function Promise(resolver) { - if (typeof resolver !== 'function') { - throw new TypeError('Promise resolver ' + resolver + ' is not a function'); - } +// for EMFILE handling +var timeout = 0 - if (this instanceof Promise === false) { - throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.'); - } +var isWindows = (process.platform === "win32") - this._then = []; +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] + }) - invokeResolver(resolver, this); + 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 } -Promise.prototype = { - constructor: Promise, +function rimraf (p, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } - _state: PENDING, - _then: null, - _data: undefined, - _handled: false, + 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') - then: function (onFulfillment, onRejection) { - var subscriber = { - owner: this, - then: new this.constructor(NOOP), - fulfilled: onFulfillment, - rejected: onRejection - }; + defaults(options) - if ((onRejection || onFulfillment) && !this._handled) { - this._handled = true; - if (this._state === REJECTED && isNode) { - asyncCall(notifyRejectionHandled, this); - } - } + var busyTries = 0 + var errState = null + var n = 0 - if (this._state === FULFILLED || this._state === REJECTED) { - // already resolved, call callback async - asyncCall(invokeCallback, subscriber); - } else { - // subscribe - this._then.push(subscriber); - } + if (options.disableGlob || !glob.hasMagic(p)) + return afterGlob(null, [p]) - return subscriber.then; - }, + options.lstat(p, function (er, stat) { + if (!er) + return afterGlob(null, [p]) - catch: function (onRejection) { - return this.then(null, onRejection); - } -}; + glob(p, options.glob, afterGlob) + }) -Promise.all = function (promises) { - if (!Array.isArray(promises)) { - throw new TypeError('You must pass an array to Promise.all().'); - } + function next (er) { + errState = errState || er + if (--n === 0) + cb(errState) + } - return new Promise(function (resolve, reject) { - var results = []; - var remaining = 0; + function afterGlob (er, results) { + if (er) + return cb(er) - function resolver(index) { - remaining++; - return function (value) { - results[index] = value; - if (!--remaining) { - resolve(results); - } - }; - } + n = results.length + if (n === 0) + return cb() - for (var i = 0, promise; i < promises.length; i++) { - promise = promises[i]; + 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) + } - if (promise && typeof promise.then === 'function') { - promise.then(resolver(i), reject); - } else { - results[i] = promise; - } - } + // 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 ++) + } - if (!remaining) { - resolve(results); - } - }); -}; + // already gone + if (er.code === "ENOENT") er = null + } -Promise.race = function (promises) { - if (!Array.isArray(promises)) { - throw new TypeError('You must pass an array to Promise.race().'); - } + timeout = 0 + next(er) + }) + }) + } +} - return new Promise(function (resolve, reject) { - for (var i = 0, promise; i < promises.length; i++) { - promise = promises[i]; +// 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') - if (promise && typeof promise.then === 'function') { - promise.then(resolve, reject); - } else { - resolve(promise); - } - } - }); -}; + // 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) -Promise.resolve = function (value) { - if (value && typeof value === 'object' && value.constructor === Promise) { - return value; - } + // Windows can EPERM on stat. Life is suffering. + if (er && er.code === "EPERM" && isWindows) + fixWinEPERM(p, options, er, cb) - return new Promise(function (resolve) { - resolve(value); - }); -}; + if (st && st.isDirectory()) + return rmdir(p, options, er, cb) -Promise.reject = function (reason) { - return new Promise(function (resolve, reject) { - reject(reason); - }); -}; + 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 = Promise; +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) + }) + }) +} -/***/ }), -/* 141 */ -/***/ (function(module, exports, __webpack_require__) { +function fixWinEPERMSync (p, options, er) { + assert(p) + assert(options) + if (er) + assert(er instanceof Error) -"use strict"; + try { + options.chmodSync(p, _0666) + } catch (er2) { + if (er2.code === "ENOENT") + return + else + throw er + } -var arrayUniq = __webpack_require__(142); + try { + var stats = options.statSync(p) + } catch (er3) { + if (er3.code === "ENOENT") + return + else + throw er + } -module.exports = function () { - return arrayUniq([].concat.apply([], arguments)); -}; + if (stats.isDirectory()) + rmdirSync(p, options, er) + else + options.unlinkSync(p) +} +function rmdir (p, options, originalEr, cb) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) + assert(typeof cb === 'function') -/***/ }), -/* 142 */ -/***/ (function(module, exports, __webpack_require__) { + // 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) + }) +} -"use strict"; +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) + }) + }) + }) +} -// there's 3 implementations written in increasing order of efficiency +// 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) -// 1 - no Set type is defined -function uniqNoSet(arr) { - var ret = []; + 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') - for (var i = 0; i < arr.length; i++) { - if (ret.indexOf(arr[i]) === -1) { - ret.push(arr[i]); - } - } + var results - return ret; -} + if (options.disableGlob || !glob.hasMagic(p)) { + results = [p] + } else { + try { + options.lstatSync(p) + results = [p] + } catch (er) { + results = glob.sync(p, options.glob) + } + } -// 2 - a simple Set type is defined -function uniqSet(arr) { - var seen = new Set(); - return arr.filter(function (el) { - if (!seen.has(el)) { - seen.add(el); - return true; - } + if (!results.length) + return - return false; - }); -} + for (var i = 0; i < results.length; i++) { + var p = results[i] -// 3 - a standard Set type is defined and it has a forEach method -function uniqSetWithForEach(arr) { - var ret = []; + try { + var st = options.lstatSync(p) + } catch (er) { + if (er.code === "ENOENT") + return - (new Set(arr)).forEach(function (el) { - ret.push(el); - }); + // Windows can EPERM on stat. Life is suffering. + if (er.code === "EPERM" && isWindows) + fixWinEPERMSync(p, options, er) + } - return ret; -} + 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 -// V8 currently has a broken implementation -// https://github.com/joyent/node/issues/8449 -function doesForEachActuallyWork() { - var ret = false; + rmdirSync(p, options, er) + } + } +} - (new Set([true])).forEach(function (el) { - ret = el; - }); +function rmdirSync (p, options, originalEr) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) - return ret === true; + 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) + } } -if ('Set' in global) { - if (typeof Set.prototype.forEach === 'function' && doesForEachActuallyWork()) { - module.exports = uniqSetWithForEach; - } else { - module.exports = uniqSet; - } -} else { - module.exports = uniqNoSet; +function rmkidsSync (p, options) { + assert(p) + assert(options) + options.readdirSync(p).forEach(function (f) { + rimrafSync(path.join(p, f), options) + }) + + // 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) } /***/ }), -/* 143 */ +/* 179 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ -/* eslint-disable no-unused-vars */ -var getOwnPropertySymbols = Object.getOwnPropertySymbols; -var hasOwnProperty = Object.prototype.hasOwnProperty; -var propIsEnumerable = Object.prototype.propertyIsEnumerable; +const pMap = (iterable, mapper, options) => new Promise((resolve, reject) => { + options = Object.assign({ + concurrency: Infinity + }, options); -function toObject(val) { - if (val === null || val === undefined) { - throw new TypeError('Object.assign cannot be called with null or undefined'); + if (typeof mapper !== 'function') { + throw new TypeError('Mapper function is required'); } - return Object(val); -} - -function shouldUseNative() { - try { - if (!Object.assign) { - return false; - } - - // Detect buggy property enumeration order in older V8 versions. + const {concurrency} = options; - // https://bugs.chromium.org/p/v8/issues/detail?id=4118 - var test1 = new String('abc'); // eslint-disable-line no-new-wrappers - test1[5] = 'de'; - if (Object.getOwnPropertyNames(test1)[0] === '5') { - return false; - } + if (!(typeof concurrency === 'number' && concurrency >= 1)) { + throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); + } - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test2 = {}; - for (var i = 0; i < 10; i++) { - test2['_' + String.fromCharCode(i)] = i; - } - var order2 = Object.getOwnPropertyNames(test2).map(function (n) { - return test2[n]; - }); - if (order2.join('') !== '0123456789') { - return false; - } + const ret = []; + const iterator = iterable[Symbol.iterator](); + let isRejected = false; + let isIterableDone = false; + let resolvingCount = 0; + let currentIndex = 0; - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test3 = {}; - 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { - test3[letter] = letter; - }); - if (Object.keys(Object.assign({}, test3)).join('') !== - 'abcdefghijklmnopqrst') { - return false; + const next = () => { + if (isRejected) { + return; } - return true; - } catch (err) { - // We don't expect any of the above to throw, but better to be safe. - return false; - } -} - -module.exports = shouldUseNative() ? Object.assign : function (target, source) { - var from; - var to = toObject(target); - var symbols; + const nextItem = iterator.next(); + const i = currentIndex; + currentIndex++; - for (var s = 1; s < arguments.length; s++) { - from = Object(arguments[s]); + if (nextItem.done) { + isIterableDone = true; - for (var key in from) { - if (hasOwnProperty.call(from, key)) { - to[key] = from[key]; + if (resolvingCount === 0) { + resolve(ret); } + + return; } - if (getOwnPropertySymbols) { - symbols = getOwnPropertySymbols(from); - for (var i = 0; i < symbols.length; i++) { - if (propIsEnumerable.call(from, symbols[i])) { - to[symbols[i]] = from[symbols[i]]; + 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; } } +}); - return to; -}; +module.exports = pMap; +// TODO: Remove this for the next major release +module.exports.default = pMap; /***/ }), -/* 144 */ +/* 180 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const chalk = __webpack_require__(181); +const cliCursor = __webpack_require__(185); +const cliSpinners = __webpack_require__(189); +const logSymbols = __webpack_require__(149); -var processFn = function (fn, P, opts) { - return function () { - var that = this; - var args = new Array(arguments.length); - - for (var i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; +class Ora { + constructor(options) { + if (typeof options === 'string') { + options = { + text: options + }; } - return new P(function (resolve, reject) { - args.push(function (err, result) { - if (err) { - reject(err); - } else if (opts.multiArgs) { - var results = new Array(arguments.length - 1); - - for (var i = 1; i < arguments.length; i++) { - results[i - 1] = arguments[i]; - } + this.options = Object.assign({ + text: '', + color: 'cyan', + stream: process.stderr + }, options); - resolve(results); - } else { - resolve(result); - } - }); + 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 - fn.apply(that, args); - }); - }; -}; + if (this.spinner.frames === undefined) { + throw new Error('Spinner must define `frames`'); + } -var pify = module.exports = function (obj, P, opts) { - if (typeof P !== 'function') { - opts = P; - P = Promise; + 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]; - opts = opts || {}; - opts.exclude = opts.exclude || [/.+Sync$/]; - - var filter = function (key) { - var match = function (pattern) { - return typeof pattern === 'string' ? key === pattern : pattern.test(key); - }; + if (this.color) { + frame = chalk[this.color](frame); + } - return opts.include ? opts.include.some(match) : !opts.exclude.some(match); - }; + this.frameIndex = ++this.frameIndex % frames.length; - var ret = typeof obj === 'function' ? function () { - if (opts.excludeMain) { - return obj.apply(this, arguments); + return frame + ' ' + this.text; + } + clear() { + if (!this.enabled) { + return this; } - return processFn(obj, P, opts).apply(this, arguments); - } : {}; + this.stream.clearLine(); + this.stream.cursorTo(0); - return Object.keys(obj).reduce(function (ret, key) { - var x = obj[key]; + return this; + } + render() { + this.clear(); + this.stream.write(this.frame()); - ret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x; + return this; + } + start(text) { + if (text) { + this.text = text; + } - return ret; - }, ret); -}; + if (!this.enabled || this.id) { + return this; + } -pify.all = pify; + cliCursor.hide(this.stream); + this.render(); + this.id = setInterval(this.render.bind(this), this.interval); + return this; + } + stop() { + if (!this.enabled) { + return this; + } -/***/ }), -/* 145 */ -/***/ (function(module, exports, __webpack_require__) { + clearInterval(this.id); + this.id = null; + this.frameIndex = 0; + this.clear(); + cliCursor.show(this.stream); -"use strict"; + 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; + } -const path = __webpack_require__(16); + // Legacy argument + // TODO: Deprecate sometime in the future + if (typeof options === 'string') { + options = { + symbol: options + }; + } -module.exports = path_ => path.resolve(path_) === process.cwd(); + options = options || {}; + this.stop(); + this.stream.write(`${options.symbol || ' '} ${options.text || this.text}\n`); -/***/ }), -/* 146 */ -/***/ (function(module, exports, __webpack_require__) { + return this; + } +} -"use strict"; +module.exports = function (opts) { + return new Ora(opts); +}; -const isPathInside = __webpack_require__(147); +module.exports.promise = (action, options) => { + if (typeof action.then !== 'function') { + throw new TypeError('Parameter `action` must be a Promise'); + } -module.exports = path => isPathInside(path, process.cwd()); + const spinner = new Ora(options); + spinner.start(); + + action.then( + () => { + spinner.succeed(); + }, + () => { + spinner.fail(); + } + ); + + return spinner; +}; /***/ }), -/* 147 */ +/* 181 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const path = __webpack_require__(16); -const pathIsInside = __webpack_require__(148); - -module.exports = (childPath, parentPath) => { - childPath = path.resolve(childPath); - parentPath = path.resolve(parentPath); - - if (childPath === parentPath) { - return false; - } +const escapeStringRegexp = __webpack_require__(3); +const ansiStyles = __webpack_require__(182); +const stdoutColor = __webpack_require__(183).stdout; - return pathIsInside(childPath, parentPath); -}; +const template = __webpack_require__(184); +const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); -/***/ }), -/* 148 */ -/***/ (function(module, exports, __webpack_require__) { +// `supportsColor.level` → `ansiStyles.color[name]` mapping +const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; -"use strict"; +// `color-convert` models to exclude from the Chalk API due to conflicts and such +const skipModels = new Set(['gray']); +const styles = Object.create(null); -var path = __webpack_require__(16); +function applyOptions(obj, options) { + options = options || {}; -module.exports = function (thePath, potentialParent) { - // For inside-directory checking, we want to allow trailing slashes, so normalize. - thePath = stripTrailingSep(thePath); - potentialParent = stripTrailingSep(potentialParent); + // 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; +} - // Node treats only Windows as case-insensitive in its path module; we follow those conventions. - if (process.platform === "win32") { - thePath = thePath.toLowerCase(); - potentialParent = potentialParent.toLowerCase(); - } +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); - return thePath.lastIndexOf(potentialParent, 0) === 0 && - ( - thePath[potentialParent.length] === path.sep || - thePath[potentialParent.length] === undefined - ); -}; + chalk.template = function () { + const args = [].slice.call(arguments); + return chalkTag.apply(null, [chalk.template].concat(args)); + }; -function stripTrailingSep(thePath) { - if (thePath[thePath.length - 1] === path.sep) { - return thePath.slice(0, -1); - } - return thePath; -} + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); + chalk.template.constructor = Chalk; -/***/ }), -/* 149 */ -/***/ (function(module, exports, __webpack_require__) { + return chalk.template; + } -"use strict"; + applyOptions(this, options); +} +// Use bright blue on Windows as the normal blue color is illegible +if (isSimpleWindowsTerm) { + ansiStyles.blue.open = '\u001B[94m'; +} -const processFn = (fn, options) => function (...args) { - const P = options.promiseModule; +for (const key of Object.keys(ansiStyles)) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); - return new P((resolve, reject) => { - if (options.multiArgs) { - args.push((...result) => { - if (options.errorFirst) { - if (result[0]) { - reject(result); - } else { - result.shift(); - resolve(result); - } - } else { - resolve(result); - } - }); - } else if (options.errorFirst) { - args.push((error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); - } else { - args.push(resolve); + styles[key] = { + get() { + const codes = ansiStyles[key]; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); } + }; +} - fn.apply(this, args); - }); +styles.visible = { + get() { + return build.call(this, this._styles || [], true, 'visible'); + } }; -module.exports = (input, options) => { - options = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, options); - - const objType = typeof input; - if (!(input !== null && (objType === 'object' || objType === 'function'))) { - throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); +ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); +for (const model of Object.keys(ansiStyles.color.ansi)) { + if (skipModels.has(model)) { + continue; } - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return options.include ? options.include.some(match) : !options.exclude.some(match); + 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); + }; + } }; +} - let ret; - if (objType === 'function') { - ret = function (...args) { - return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); - }; - } else { - ret = Object.create(Object.getPrototypeOf(input)); - } - - for (const key in input) { // eslint-disable-line guard-for-in - const property = input[key]; - ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; +ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); +for (const model of Object.keys(ansiStyles.bgColor.ansi)) { + if (skipModels.has(model)) { + continue; } - return ret; -}; + 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); -/***/ }), -/* 150 */ -/***/ (function(module, exports, __webpack_require__) { +function build(_styles, _empty, key) { + const builder = function () { + return applyStyle.apply(builder, arguments); + }; -module.exports = rimraf -rimraf.sync = rimrafSync + builder._styles = _styles; + builder._empty = _empty; -var assert = __webpack_require__(30) -var path = __webpack_require__(16) -var fs = __webpack_require__(23) -var glob = __webpack_require__(36) -var _0666 = parseInt('666', 8) + const self = this; -var defaultGlobOpts = { - nosort: true, - silent: true -} + Object.defineProperty(builder, 'level', { + enumerable: true, + get() { + return self.level; + }, + set(level) { + self.level = level; + } + }); -// for EMFILE handling -var timeout = 0 + Object.defineProperty(builder, 'enabled', { + enumerable: true, + get() { + return self.enabled; + }, + set(enabled) { + self.enabled = enabled; + } + }); -var isWindows = (process.platform === "win32") + // See below for fix regarding invisible grey/dim combination on Windows + builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; -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] - }) + // `__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 - 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 + return builder; } -function rimraf (p, options, cb) { - if (typeof options === 'function') { - cb = options - options = {} - } - - 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') - - defaults(options) - - var busyTries = 0 - var errState = null - var n = 0 - - if (options.disableGlob || !glob.hasMagic(p)) - return afterGlob(null, [p]) +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]); - options.lstat(p, function (er, stat) { - if (!er) - return afterGlob(null, [p]) + if (argsLen === 0) { + return ''; + } - glob(p, options.glob, afterGlob) - }) + if (argsLen > 1) { + // Don't slice `arguments`, it prevents V8 optimizations + for (let a = 1; a < argsLen; a++) { + str += ' ' + args[a]; + } + } - function next (er) { - errState = errState || er - if (--n === 0) - cb(errState) - } + if (!this.enabled || this.level <= 0 || !str) { + return this._empty ? '' : str; + } - function afterGlob (er, results) { - if (er) - return cb(er) + // 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 = ''; + } - n = results.length - if (n === 0) - return cb() + 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; - 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) - } + // 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}`); + } - // 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 ++) - } + // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue + ansiStyles.dim.open = originalDim; - // already gone - if (er.code === "ENOENT") er = null - } + return str; +} - timeout = 0 - next(er) - }) - }) - } +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('')); } -// 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') +Object.defineProperties(Chalk.prototype, styles); - // 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) +module.exports = Chalk(); // eslint-disable-line new-cap +module.exports.supportsColor = stdoutColor; +module.exports.default = module.exports; // For TypeScript - // Windows can EPERM on stat. Life is suffering. - if (er && er.code === "EPERM" && isWindows) - fixWinEPERM(p, options, er, cb) - if (st && st.isDirectory()) - return rmdir(p, options, er, cb) +/***/ }), +/* 182 */ +/***/ (function(module, exports, __webpack_require__) { - 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) - }) - }) -} +"use strict"; +/* WEBPACK VAR INJECTION */(function(module) { +const colorConvert = __webpack_require__(6); -function fixWinEPERM (p, options, er, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - if (er) - assert(er instanceof Error) +const wrapAnsi16 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${code + offset}m`; +}; - 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) - }) - }) -} +const wrapAnsi256 = (fn, offset) => function () { + const code = fn.apply(colorConvert, arguments); + return `\u001B[${38 + offset};5;${code}m`; +}; -function fixWinEPERMSync (p, options, er) { - assert(p) - assert(options) - if (er) - assert(er instanceof Error) +const wrapAnsi16m = (fn, offset) => function () { + const rgb = fn.apply(colorConvert, arguments); + return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; +}; - try { - options.chmodSync(p, _0666) - } catch (er2) { - if (er2.code === "ENOENT") - return - else - throw er - } +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], - try { - var stats = options.statSync(p) - } catch (er3) { - if (er3.code === "ENOENT") - return - else - throw er - } + // 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], - if (stats.isDirectory()) - rmdirSync(p, options, er) - else - options.unlinkSync(p) -} + // 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] + } + }; -function rmdir (p, options, originalEr, cb) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) - assert(typeof cb === 'function') + // Fix humans + styles.color.grey = styles.color.gray; - // 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) - }) -} + for (const groupName of Object.keys(styles)) { + const group = styles[groupName]; -function rmkids(p, options, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') + for (const styleName of Object.keys(group)) { + const style = group[styleName]; - 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) - }) - }) - }) -} + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m` + }; -// 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) + group[styleName] = styles[styleName]; - 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') + codes.set(style[0], style[1]); + } - var results + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); - if (options.disableGlob || !glob.hasMagic(p)) { - results = [p] - } else { - try { - options.lstatSync(p) - results = [p] - } catch (er) { - results = glob.sync(p, options.glob) - } - } + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); + } - if (!results.length) - return + const ansi2ansi = n => n; + const rgb2rgb = (r, g, b) => [r, g, b]; - for (var i = 0; i < results.length; i++) { - var p = results[i] + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; - try { - var st = options.lstatSync(p) - } catch (er) { - if (er.code === "ENOENT") - return + styles.color.ansi = { + ansi: wrapAnsi16(ansi2ansi, 0) + }; + styles.color.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 0) + }; + styles.color.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 0) + }; - // Windows can EPERM on stat. Life is suffering. - if (er.code === "EPERM" && isWindows) - fixWinEPERMSync(p, options, er) - } + styles.bgColor.ansi = { + ansi: wrapAnsi16(ansi2ansi, 10) + }; + styles.bgColor.ansi256 = { + ansi256: wrapAnsi256(ansi2ansi, 10) + }; + styles.bgColor.ansi16m = { + rgb: wrapAnsi16m(rgb2rgb, 10) + }; - 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 + for (let key of Object.keys(colorConvert)) { + if (typeof colorConvert[key] !== 'object') { + continue; + } - rmdirSync(p, options, er) - } - } -} + const suite = colorConvert[key]; -function rmdirSync (p, options, originalEr) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) + if (key === 'ansi16') { + key = 'ansi'; + } - 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) - } -} + if ('ansi16' in suite) { + styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0); + styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10); + } -function rmkidsSync (p, options) { - assert(p) - assert(options) - options.readdirSync(p).forEach(function (f) { - rimrafSync(path.join(p, f), options) - }) + if ('ansi256' in suite) { + styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0); + styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10); + } - // 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) + 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__(5)(module))) /***/ }), -/* 151 */ +/* 183 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const os = __webpack_require__(11); +const hasFlag = __webpack_require__(12); -const pMap = (iterable, mapper, options) => new Promise((resolve, reject) => { - options = Object.assign({ - concurrency: Infinity - }, options); +const env = process.env; - if (typeof mapper !== 'function') { - throw new TypeError('Mapper function is required'); +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + forceColor = false; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = true; +} +if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; +} + +function translateLevel(level) { + if (level === 0) { + return false; } - const {concurrency} = options; + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +} - if (!(typeof concurrency === 'number' && concurrency >= 1)) { - throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); +function supportsColor(stream) { + if (forceColor === false) { + return 0; } - const ret = []; - const iterator = iterable[Symbol.iterator](); - let isRejected = false; - let isIterableDone = false; - let resolvingCount = 0; - let currentIndex = 0; + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } - const next = () => { - if (isRejected) { - return; + if (hasFlag('color=256')) { + return 2; + } + + if (stream && !stream.isTTY && forceColor !== true) { + // VS code debugger doesn't have isTTY set + if (env.VSCODE_PID) { + return 1; } + return 0; + } - const nextItem = iterator.next(); - const i = currentIndex; - currentIndex++; + const min = forceColor ? 1 : 0; - if (nextItem.done) { - isIterableDone = true; + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. 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(process.versions.node.split('.')[0]) >= 8 && + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } - if (resolvingCount === 0) { - resolve(ret); - } + 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; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } + + if (env.COLORTERM === 'truecolor') { + return 3; + } + + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); - return; + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default } + } - resolvingCount++; + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } - Promise.resolve(nextItem.value) - .then(element => mapper(element, i)) - .then( - value => { - ret[i] = value; - resolvingCount--; - next(); - }, - error => { - isRejected = true; - reject(error); - } - ); - }; + if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } - for (let i = 0; i < concurrency; i++) { - next(); + if ('COLORTERM' in env) { + return 1; + } - if (isIterableDone) { - break; - } + if (env.TERM === 'dumb') { + return min; } -}); -module.exports = pMap; -// TODO: Remove this for the next major release -module.exports.default = pMap; + return min; +} + +function getSupportLevel(stream) { + const level = supportsColor(stream); + return translateLevel(level); +} + +module.exports = { + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr) +}; /***/ }), -/* 152 */ +/* 184 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(2); -const cliCursor = __webpack_require__(153); -const cliSpinners = __webpack_require__(157); -const logSymbols = __webpack_require__(125); - -class Ora { - constructor(options) { - if (typeof options === 'string') { - options = { - text: options - }; - } +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; - this.options = Object.assign({ - text: '', - color: 'cyan', - stream: process.stderr - }, options); +const ESCAPES = new Map([ + ['n', '\n'], + ['r', '\r'], + ['t', '\t'], + ['b', '\b'], + ['f', '\f'], + ['v', '\v'], + ['0', '\0'], + ['\\', '\\'], + ['e', '\u001B'], + ['a', '\u0007'] +]); - 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 +function unescape(c) { + if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) { + return String.fromCharCode(parseInt(c.slice(1), 16)); + } - if (this.spinner.frames === undefined) { - throw new Error('Spinner must define `frames`'); - } + return ESCAPES.get(c) || c; +} - 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]; +function parseArguments(name, args) { + const results = []; + const chunks = args.trim().split(/\s*,\s*/g); + let matches; - if (this.color) { - frame = chalk[this.color](frame); + 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}')`); } + } - this.frameIndex = ++this.frameIndex % frames.length; + return results; +} - return frame + ' ' + this.text; - } - clear() { - if (!this.enabled) { - return this; - } +function parseStyle(style) { + STYLE_REGEX.lastIndex = 0; - this.stream.clearLine(); - this.stream.cursorTo(0); + const results = []; + let matches; - return this; - } - render() { - this.clear(); - this.stream.write(this.frame()); + while ((matches = STYLE_REGEX.exec(style)) !== null) { + const name = matches[1]; - return this; - } - start(text) { - if (text) { - this.text = text; + if (matches[2]) { + const args = parseArguments(name, matches[2]); + results.push([name].concat(args)); + } else { + results.push([name]); } + } - if (!this.enabled || this.id) { - return this; - } + return results; +} - cliCursor.hide(this.stream); - this.render(); - this.id = setInterval(this.render.bind(this), this.interval); +function buildStyle(chalk, styles) { + const enabled = {}; - return this; - } - stop() { - if (!this.enabled) { - return this; + for (const layer of styles) { + for (const style of layer.styles) { + enabled[style[0]] = layer.inverse ? null : style.slice(1); } + } - clearInterval(this.id); - this.id = null; - this.frameIndex = 0; - this.clear(); - cliCursor.show(this.stream); + 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}`); + } - 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; + if (enabled[styleName].length > 0) { + current = current[styleName].apply(current, enabled[styleName]); + } else { + current = current[styleName]; + } } + } - // Legacy argument - // TODO: Deprecate sometime in the future - if (typeof options === 'string') { - options = { - symbol: options - }; - } + return current; +} - options = options || {}; +module.exports = (chalk, tmp) => { + const styles = []; + const chunks = []; + let chunk = []; - this.stop(); - this.stream.write(`${options.symbol || ' '} ${options.text || this.text}\n`); + // 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'); + } - return this; - } -} + chunks.push(buildStyle(chalk, styles)(chunk.join(''))); + chunk = []; + styles.pop(); + } else { + chunk.push(chr); + } + }); -module.exports = function (opts) { - return new Ora(opts); -}; + chunks.push(chunk.join('')); -module.exports.promise = (action, options) => { - if (typeof action.then !== 'function') { - throw new TypeError('Parameter `action` must be a Promise'); + if (styles.length > 0) { + const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; + throw new Error(errMsg); } - const spinner = new Ora(options); - spinner.start(); - - action.then( - () => { - spinner.succeed(); - }, - () => { - spinner.fail(); - } - ); - - return spinner; + return chunks.join(''); }; /***/ }), -/* 153 */ +/* 185 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(154); +const restoreCursor = __webpack_require__(186); let hidden = false; @@ -19558,13 +26033,13 @@ exports.toggle = (force, stream) => { /***/ }), -/* 154 */ +/* 186 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(155); -const signalExit = __webpack_require__(87); +const onetime = __webpack_require__(187); +const signalExit = __webpack_require__(110); module.exports = onetime(() => { signalExit(() => { @@ -19574,12 +26049,12 @@ module.exports = onetime(() => { /***/ }), -/* 155 */ +/* 187 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(156); +const mimicFn = __webpack_require__(188); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -19620,7 +26095,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 156 */ +/* 188 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -19636,22 +26111,22 @@ module.exports = (to, from) => { /***/ }), -/* 157 */ +/* 189 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(158); +module.exports = __webpack_require__(190); /***/ }), -/* 158 */ +/* 190 */ /***/ (function(module) { -module.exports = {"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":["🌲","🎄"]}}; +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\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 159 */ +/* 191 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -19659,9 +26134,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RunCommand", function() { return RunCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(35); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(35); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(36); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -19711,7 +26186,7 @@ const RunCommand = { }; /***/ }), -/* 160 */ +/* 192 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -19719,10 +26194,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(35); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(161); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(35); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(36); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(193); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -19806,14 +26281,14 @@ const WatchCommand = { }; /***/ }), -/* 161 */ +/* 193 */ /***/ (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__(162); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(261); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(194); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(293); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -19880,168 +26355,168 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 162 */ +/* 194 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return _internal_Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]; }); -/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(181); +/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__["ConnectableObservable"]; }); -/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(186); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(218); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__["GroupedObservable"]; }); -/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(178); +/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(210); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observable", function() { return _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__["observable"]; }); -/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(182); +/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(214); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return _internal_Subject__WEBPACK_IMPORTED_MODULE_4__["Subject"]; }); -/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(187); +/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(219); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__["BehaviorSubject"]; }); -/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(188); +/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__["ReplaySubject"]; }); -/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(205); +/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(237); /* 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__(206); +/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(238); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asap"]; }); -/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(210); +/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(242); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["async"]; }); -/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(189); +/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(221); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; }); -/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(211); +/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(243); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; }); -/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(214); +/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(246); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualTimeScheduler"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualAction"]; }); -/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(195); +/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(227); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Scheduler", function() { return _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__["Scheduler"]; }); -/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(171); +/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(203); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__["Subscription"]; }); -/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(165); +/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(197); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__["Subscriber"]; }); -/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(197); +/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(229); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return _internal_Notification__WEBPACK_IMPORTED_MODULE_16__["Notification"]; }); -/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(179); +/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(211); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__["pipe"]; }); -/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(180); +/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(212); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "noop", function() { return _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__["noop"]; }); -/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(215); +/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(247); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "identity", function() { return _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__["identity"]; }); -/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(216); +/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(248); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__["isObservable"]; }); -/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(217); +/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(249); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__["ArgumentOutOfRangeError"]; }); -/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(218); +/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(250); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__["EmptyError"]; }); -/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(183); +/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(215); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__["ObjectUnsubscribedError"]; }); -/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(176); +/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(208); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__["UnsubscriptionError"]; }); -/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(219); +/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(251); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__["TimeoutError"]; }); -/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(220); +/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(252); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__["bindCallback"]; }); -/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(222); +/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(254); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__["bindNodeCallback"]; }); -/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(223); +/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(255); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__["combineLatest"]; }); -/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(234); +/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(266); /* 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__(244); +/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(276); /* 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__(198); +/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(230); /* 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__(245); +/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(277); /* 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__(235); +/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(267); /* 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__(246); +/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(278); /* 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__(247); +/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(279); /* 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__(248); +/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(280); /* 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__(249); +/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(281); /* 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__(250); +/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(282); /* 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__(252); +/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(284); /* 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__(253); +/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(285); /* 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__(199); +/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(231); /* 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__(254); +/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(286); /* 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__(255); +/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(287); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__["pairs"]; }); -/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(256); +/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(288); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__["race"]; }); -/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(257); +/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(289); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__["range"]; }); -/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(204); +/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(236); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__["throwError"]; }); -/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(258); +/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(290); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__["timer"]; }); -/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(259); +/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(291); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__["using"]; }); -/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(260); +/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(292); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__["zip"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["EMPTY"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["NEVER"]; }); -/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(169); +/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(201); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "config", function() { return _internal_config__WEBPACK_IMPORTED_MODULE_50__["config"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -20102,16 +26577,16 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 163 */ +/* 195 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return Observable; }); -/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(164); -/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(178); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(179); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(169); +/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); +/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(210); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(211); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(201); /** PURE_IMPORTS_START _util_toSubscriber,_internal_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */ @@ -20225,15 +26700,15 @@ function getPromiseCtor(promiseCtor) { /***/ }), -/* 164 */ +/* 196 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toSubscriber", function() { return toSubscriber; }); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(165); -/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(177); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(168); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(197); +/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(209); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); /** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */ @@ -20256,19 +26731,19 @@ function toSubscriber(nextOrObserver, error, complete) { /***/ }), -/* 165 */ +/* 197 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return Subscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(167); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(168); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(171); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(177); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(169); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(170); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(199); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(203); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(209); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(201); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(202); /** PURE_IMPORTS_START tslib,_util_isFunction,_Observer,_Subscription,_internal_symbol_rxSubscriber,_config,_util_hostReportError PURE_IMPORTS_END */ @@ -20510,7 +26985,7 @@ function isTrustedSubscriber(obj) { /***/ }), -/* 166 */ +/* 198 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -20723,7 +27198,7 @@ function __importDefault(mod) { /***/ }), -/* 167 */ +/* 199 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -20737,14 +27212,14 @@ function isFunction(x) { /***/ }), -/* 168 */ +/* 200 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(169); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(170); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(201); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(202); /** PURE_IMPORTS_START _config,_util_hostReportError PURE_IMPORTS_END */ @@ -20765,7 +27240,7 @@ var empty = { /***/ }), -/* 169 */ +/* 201 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -20793,7 +27268,7 @@ var config = { /***/ }), -/* 170 */ +/* 202 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -20807,18 +27282,18 @@ function hostReportError(err) { /***/ }), -/* 171 */ +/* 203 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return Subscription; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(172); -/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(173); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(167); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(175); -/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(176); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(205); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(199); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(207); +/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(208); /** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_tryCatch,_util_errorObject,_util_UnsubscriptionError PURE_IMPORTS_END */ @@ -20954,7 +27429,7 @@ function flattenUnsubscriptionErrors(errors) { /***/ }), -/* 172 */ +/* 204 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -20966,7 +27441,7 @@ var isArray = Array.isArray || (function (x) { return x && typeof x.length === ' /***/ }), -/* 173 */ +/* 205 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -20980,13 +27455,13 @@ function isObject(x) { /***/ }), -/* 174 */ +/* 206 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tryCatch", function() { return tryCatch; }); -/* harmony import */ var _errorObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(175); +/* harmony import */ var _errorObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); /** PURE_IMPORTS_START _errorObject PURE_IMPORTS_END */ var tryCatchTarget; @@ -21007,7 +27482,7 @@ function tryCatch(fn) { /***/ }), -/* 175 */ +/* 207 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -21019,13 +27494,13 @@ var errorObject = { e: {} }; /***/ }), -/* 176 */ +/* 208 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return UnsubscriptionError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var UnsubscriptionError = /*@__PURE__*/ (function (_super) { @@ -21045,7 +27520,7 @@ var UnsubscriptionError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 177 */ +/* 209 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -21061,7 +27536,7 @@ var $$rxSubscriber = rxSubscriber; /***/ }), -/* 178 */ +/* 210 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -21073,14 +27548,14 @@ var observable = typeof Symbol === 'function' && Symbol.observable || '@@observa /***/ }), -/* 179 */ +/* 211 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return pipe; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipeFromArray", function() { return pipeFromArray; }); -/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(180); +/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(212); /** PURE_IMPORTS_START _noop PURE_IMPORTS_END */ function pipe() { @@ -21105,7 +27580,7 @@ function pipeFromArray(fns) { /***/ }), -/* 180 */ +/* 212 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -21117,19 +27592,19 @@ function noop() { } /***/ }), -/* 181 */ +/* 213 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return ConnectableObservable; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "connectableObservableDescriptor", function() { return connectableObservableDescriptor; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(163); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(165); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(171); -/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(185); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(195); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(197); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(203); +/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(217); /** PURE_IMPORTS_START tslib,_Subject,_Observable,_Subscriber,_Subscription,_operators_refCount PURE_IMPORTS_END */ @@ -21276,7 +27751,7 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 182 */ +/* 214 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -21284,13 +27759,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscriber", function() { return SubjectSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return Subject; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnonymousSubject", function() { return AnonymousSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(163); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(165); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(171); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(183); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(184); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(177); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(195); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(197); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(203); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(215); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(216); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(209); /** PURE_IMPORTS_START tslib,_Observable,_Subscriber,_Subscription,_util_ObjectUnsubscribedError,_SubjectSubscription,_internal_symbol_rxSubscriber PURE_IMPORTS_END */ @@ -21452,13 +27927,13 @@ var AnonymousSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 183 */ +/* 215 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return ObjectUnsubscribedError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var ObjectUnsubscribedError = /*@__PURE__*/ (function (_super) { @@ -21476,14 +27951,14 @@ var ObjectUnsubscribedError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 184 */ +/* 216 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscription", function() { return SubjectSubscription; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -21519,14 +27994,14 @@ var SubjectSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 185 */ +/* 217 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return refCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -21588,18 +28063,18 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 186 */ +/* 218 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return groupBy; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return GroupedObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(171); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(163); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(182); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(203); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(195); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(214); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription,_Observable,_Subject PURE_IMPORTS_END */ @@ -21785,15 +28260,15 @@ var InnerRefCountSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 187 */ +/* 219 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return BehaviorSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(183); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); /** PURE_IMPORTS_START tslib,_Subject,_util_ObjectUnsubscribedError PURE_IMPORTS_END */ @@ -21840,19 +28315,19 @@ var BehaviorSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 188 */ +/* 220 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return ReplaySubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(189); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(171); -/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(196); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(183); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(184); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(221); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(203); +/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(228); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(215); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(216); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_queue,_Subscription,_operators_observeOn,_util_ObjectUnsubscribedError,_SubjectSubscription PURE_IMPORTS_END */ @@ -21973,14 +28448,14 @@ var ReplayEvent = /*@__PURE__*/ (function () { /***/ }), -/* 189 */ +/* 221 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return queue; }); -/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(190); -/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(193); +/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(222); +/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(225); /** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */ @@ -21989,14 +28464,14 @@ var queue = /*@__PURE__*/ new _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__["Queu /***/ }), -/* 190 */ +/* 222 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueAction", function() { return QueueAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(191); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -22041,14 +28516,14 @@ var QueueAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 191 */ +/* 223 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncAction", function() { return AsyncAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(192); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); /** PURE_IMPORTS_START tslib,_Action PURE_IMPORTS_END */ @@ -22146,14 +28621,14 @@ var AsyncAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 192 */ +/* 224 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Action", function() { return Action; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -22175,14 +28650,14 @@ var Action = /*@__PURE__*/ (function (_super) { /***/ }), -/* 193 */ +/* 225 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueScheduler", function() { return QueueScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(194); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -22198,14 +28673,14 @@ var QueueScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 194 */ +/* 226 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncScheduler", function() { return AsyncScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(195); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227); /** PURE_IMPORTS_START tslib,_Scheduler PURE_IMPORTS_END */ @@ -22267,7 +28742,7 @@ var AsyncScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 195 */ +/* 227 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -22295,7 +28770,7 @@ var Scheduler = /*@__PURE__*/ (function () { /***/ }), -/* 196 */ +/* 228 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -22304,9 +28779,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnOperator", function() { return ObserveOnOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnSubscriber", function() { return ObserveOnSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnMessage", function() { return ObserveOnMessage; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(197); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(229); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -22376,15 +28851,15 @@ var ObserveOnMessage = /*@__PURE__*/ (function () { /***/ }), -/* 197 */ +/* 229 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return Notification; }); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); -/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(199); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(230); +/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(231); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(236); /** PURE_IMPORTS_START _observable_empty,_observable_of,_observable_throwError PURE_IMPORTS_END */ @@ -22458,7 +28933,7 @@ var Notification = /*@__PURE__*/ (function () { /***/ }), -/* 198 */ +/* 230 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -22466,7 +28941,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return EMPTY; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "emptyScheduled", function() { return emptyScheduled; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ var EMPTY = /*@__PURE__*/ new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) { return subscriber.complete(); }); @@ -22480,16 +28955,16 @@ function emptyScheduled(scheduler) { /***/ }), -/* 199 */ +/* 231 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "of", function() { return of; }); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(200); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(201); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); -/* harmony import */ var _scalar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(203); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(232); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); +/* harmony import */ var _scalar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(235); /** PURE_IMPORTS_START _util_isScheduler,_fromArray,_empty,_scalar PURE_IMPORTS_END */ @@ -22520,7 +28995,7 @@ function of() { /***/ }), -/* 200 */ +/* 232 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -22534,15 +29009,15 @@ function isScheduler(value) { /***/ }), -/* 201 */ +/* 233 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromArray", function() { return fromArray; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); -/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(202); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); +/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(234); /** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToArray PURE_IMPORTS_END */ @@ -22573,7 +29048,7 @@ function fromArray(input, scheduler) { /***/ }), -/* 202 */ +/* 234 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -22594,13 +29069,13 @@ var subscribeToArray = function (array) { /***/ }), -/* 203 */ +/* 235 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scalar", function() { return scalar; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function scalar(value) { @@ -22616,13 +29091,13 @@ function scalar(value) { /***/ }), -/* 204 */ +/* 236 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return throwError; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function throwError(error, scheduler) { @@ -22641,15 +29116,15 @@ function dispatch(_a) { /***/ }), -/* 205 */ +/* 237 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return AsyncSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(171); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(203); /** PURE_IMPORTS_START tslib,_Subject,_Subscription PURE_IMPORTS_END */ @@ -22700,14 +29175,14 @@ var AsyncSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 206 */ +/* 238 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return asap; }); -/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(209); +/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(239); +/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(241); /** PURE_IMPORTS_START _AsapAction,_AsapScheduler PURE_IMPORTS_END */ @@ -22716,15 +29191,15 @@ var asap = /*@__PURE__*/ new _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__["AsapSc /***/ }), -/* 207 */ +/* 239 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapAction", function() { return AsapAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(208); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(191); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(223); /** PURE_IMPORTS_START tslib,_util_Immediate,_AsyncAction PURE_IMPORTS_END */ @@ -22767,7 +29242,7 @@ var AsapAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 208 */ +/* 240 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -22797,14 +29272,14 @@ var Immediate = { /***/ }), -/* 209 */ +/* 241 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapScheduler", function() { return AsapScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(194); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -22841,14 +29316,14 @@ var AsapScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 210 */ +/* 242 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "async", function() { return async; }); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(191); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(194); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(223); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226); /** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -22857,14 +29332,14 @@ var async = /*@__PURE__*/ new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__["Asyn /***/ }), -/* 211 */ +/* 243 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return animationFrame; }); -/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(212); -/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); +/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(244); +/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(245); /** PURE_IMPORTS_START _AnimationFrameAction,_AnimationFrameScheduler PURE_IMPORTS_END */ @@ -22873,14 +29348,14 @@ var animationFrame = /*@__PURE__*/ new _AnimationFrameScheduler__WEBPACK_IMPORTE /***/ }), -/* 212 */ +/* 244 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameAction", function() { return AnimationFrameAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(191); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -22922,14 +29397,14 @@ var AnimationFrameAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 213 */ +/* 245 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameScheduler", function() { return AnimationFrameScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(194); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -22966,16 +29441,16 @@ var AnimationFrameScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 214 */ +/* 246 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return VirtualTimeScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return VirtualAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(191); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(194); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(226); /** PURE_IMPORTS_START tslib,_AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -23087,7 +29562,7 @@ var VirtualAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 215 */ +/* 247 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23101,13 +29576,13 @@ function identity(x) { /***/ }), -/* 216 */ +/* 248 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return isObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function isObservable(obj) { @@ -23117,13 +29592,13 @@ function isObservable(obj) { /***/ }), -/* 217 */ +/* 249 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return ArgumentOutOfRangeError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var ArgumentOutOfRangeError = /*@__PURE__*/ (function (_super) { @@ -23141,13 +29616,13 @@ var ArgumentOutOfRangeError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 218 */ +/* 250 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return EmptyError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var EmptyError = /*@__PURE__*/ (function (_super) { @@ -23165,13 +29640,13 @@ var EmptyError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 219 */ +/* 251 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return TimeoutError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var TimeoutError = /*@__PURE__*/ (function (_super) { @@ -23189,17 +29664,17 @@ var TimeoutError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 220 */ +/* 252 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return bindCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(205); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(221); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(172); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(200); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(237); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(253); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(204); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(232); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isArray,_util_isScheduler PURE_IMPORTS_END */ @@ -23302,15 +29777,15 @@ function dispatchError(state) { /***/ }), -/* 221 */ +/* 253 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "map", function() { return map; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MapOperator", function() { return MapOperator; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -23359,17 +29834,17 @@ var MapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 222 */ +/* 254 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return bindNodeCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(205); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(221); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(200); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(172); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(237); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(253); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(232); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(204); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isScheduler,_util_isArray PURE_IMPORTS_END */ @@ -23480,7 +29955,7 @@ function dispatchError(arg) { /***/ }), -/* 223 */ +/* 255 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23488,12 +29963,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestOperator", function() { return CombineLatestOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestSubscriber", function() { return CombineLatestSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(200); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(172); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(201); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(233); /** PURE_IMPORTS_START tslib,_util_isScheduler,_util_isArray,_OuterSubscriber,_util_subscribeToResult,_fromArray PURE_IMPORTS_END */ @@ -23598,14 +30073,14 @@ var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 224 */ +/* 256 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OuterSubscriber", function() { return OuterSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -23630,14 +30105,14 @@ var OuterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 225 */ +/* 257 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToResult", function() { return subscribeToResult; }); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(226); -/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227); +/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(258); +/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(259); /** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo PURE_IMPORTS_END */ @@ -23649,14 +30124,14 @@ function subscribeToResult(outerSubscriber, result, outerValue, outerIndex) { /***/ }), -/* 226 */ +/* 258 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InnerSubscriber", function() { return InnerSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -23688,22 +30163,22 @@ var InnerSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 227 */ +/* 259 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeTo", function() { return subscribeTo; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(202); -/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(228); -/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(229); -/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(231); -/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(232); -/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(233); -/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(173); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(230); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(178); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(234); +/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(260); +/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(261); +/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(263); +/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(264); +/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(265); +/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(205); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(262); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(210); /** PURE_IMPORTS_START _Observable,_subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */ @@ -23751,13 +30226,13 @@ var subscribeTo = function (result) { /***/ }), -/* 228 */ +/* 260 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToPromise", function() { return subscribeToPromise; }); -/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(170); +/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(202); /** PURE_IMPORTS_START _hostReportError PURE_IMPORTS_END */ var subscribeToPromise = function (promise) { @@ -23776,13 +30251,13 @@ var subscribeToPromise = function (promise) { /***/ }), -/* 229 */ +/* 261 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToIterable", function() { return subscribeToIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(230); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(262); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ var subscribeToIterable = function (iterable) { @@ -23813,7 +30288,7 @@ var subscribeToIterable = function (iterable) { /***/ }), -/* 230 */ +/* 262 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23834,13 +30309,13 @@ var $$iterator = iterator; /***/ }), -/* 231 */ +/* 263 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToObservable", function() { return subscribeToObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(178); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(210); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ var subscribeToObservable = function (obj) { @@ -23858,7 +30333,7 @@ var subscribeToObservable = function (obj) { /***/ }), -/* 232 */ +/* 264 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23870,7 +30345,7 @@ var isArrayLike = (function (x) { return x && typeof x.length === 'number' && ty /***/ }), -/* 233 */ +/* 265 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23884,16 +30359,16 @@ function isPromise(value) { /***/ }), -/* 234 */ +/* 266 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(200); -/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(199); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(235); -/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(241); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(232); +/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(231); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(267); +/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(273); /** PURE_IMPORTS_START _util_isScheduler,_of,_from,_operators_concatAll PURE_IMPORTS_END */ @@ -23913,22 +30388,22 @@ function concat() { /***/ }), -/* 235 */ +/* 267 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "from", function() { return from; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); -/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(232); -/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(236); -/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(237); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(201); -/* harmony import */ var _fromPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(238); -/* harmony import */ var _fromIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(239); -/* harmony import */ var _fromObservable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(240); -/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(227); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(264); +/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(268); +/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(269); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(233); +/* harmony import */ var _fromPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(270); +/* harmony import */ var _fromIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(271); +/* harmony import */ var _fromObservable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(272); +/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(259); /** PURE_IMPORTS_START _Observable,_util_isPromise,_util_isArrayLike,_util_isInteropObservable,_util_isIterable,_fromArray,_fromPromise,_fromIterable,_fromObservable,_util_subscribeTo PURE_IMPORTS_END */ @@ -23967,13 +30442,13 @@ function from(input, scheduler) { /***/ }), -/* 236 */ +/* 268 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInteropObservable", function() { return isInteropObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(178); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(210); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ function isInteropObservable(input) { @@ -23983,13 +30458,13 @@ function isInteropObservable(input) { /***/ }), -/* 237 */ +/* 269 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIterable", function() { return isIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(230); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(262); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ function isIterable(input) { @@ -23999,15 +30474,15 @@ function isIterable(input) { /***/ }), -/* 238 */ +/* 270 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromPromise", function() { return fromPromise; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); -/* harmony import */ var _util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(228); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); +/* harmony import */ var _util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(260); /** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToPromise PURE_IMPORTS_END */ @@ -24037,16 +30512,16 @@ function fromPromise(input, scheduler) { /***/ }), -/* 239 */ +/* 271 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromIterable", function() { return fromIterable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); -/* harmony import */ var _util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(229); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(262); +/* harmony import */ var _util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(261); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator,_util_subscribeToIterable PURE_IMPORTS_END */ @@ -24102,16 +30577,16 @@ function fromIterable(input, scheduler) { /***/ }), -/* 240 */ +/* 272 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromObservable", function() { return fromObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(178); -/* harmony import */ var _util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(231); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(210); +/* harmony import */ var _util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(263); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable,_util_subscribeToObservable PURE_IMPORTS_END */ @@ -24140,13 +30615,13 @@ function fromObservable(input, scheduler) { /***/ }), -/* 241 */ +/* 273 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return concatAll; }); -/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); +/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(274); /** PURE_IMPORTS_START _mergeAll PURE_IMPORTS_END */ function concatAll() { @@ -24156,14 +30631,14 @@ function concatAll() { /***/ }), -/* 242 */ +/* 274 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return mergeAll; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(243); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(247); /** PURE_IMPORTS_START _mergeMap,_util_identity PURE_IMPORTS_END */ @@ -24177,7 +30652,7 @@ function mergeAll(concurrent) { /***/ }), -/* 243 */ +/* 275 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -24185,11 +30660,11 @@ __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 import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(225); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(224); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(221); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(235); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(256); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(253); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(267); /** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_map,_observable_from PURE_IMPORTS_END */ @@ -24288,15 +30763,15 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 244 */ +/* 276 */ /***/ (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; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(267); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -24319,19 +30794,19 @@ function defer(observableFactory) { /***/ }), -/* 245 */ +/* 277 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return forkJoin; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(163); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(172); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(224); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(221); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(195); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(230); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(256); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(253); /** PURE_IMPORTS_START tslib,_Observable,_util_isArray,_empty,_util_subscribeToResult,_OuterSubscriber,_operators_map PURE_IMPORTS_END */ @@ -24409,16 +30884,16 @@ var ForkJoinSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 246 */ +/* 278 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return fromEvent; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(172); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(167); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(221); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(199); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(253); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -24485,16 +30960,16 @@ function isEventTarget(sourceObj) { /***/ }), -/* 247 */ +/* 279 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return fromEventPattern; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(172); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(167); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(221); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(199); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(253); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -24530,15 +31005,15 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) { /***/ }), -/* 248 */ +/* 280 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return generate; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(247); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(232); /** PURE_IMPORTS_START _Observable,_util_identity,_util_isScheduler PURE_IMPORTS_END */ @@ -24667,14 +31142,14 @@ function dispatch(state) { /***/ }), -/* 249 */ +/* 281 */ /***/ (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__(244); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(230); /** PURE_IMPORTS_START _defer,_empty PURE_IMPORTS_END */ @@ -24691,15 +31166,15 @@ function iif(condition, trueResult, falseResult) { /***/ }), -/* 250 */ +/* 282 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(163); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(210); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(283); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric PURE_IMPORTS_END */ @@ -24731,13 +31206,13 @@ function dispatch(state) { /***/ }), -/* 251 */ +/* 283 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNumeric", function() { return isNumeric; }); -/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(172); +/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); /** PURE_IMPORTS_START _isArray PURE_IMPORTS_END */ function isNumeric(val) { @@ -24747,16 +31222,16 @@ function isNumeric(val) { /***/ }), -/* 252 */ +/* 284 */ /***/ (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__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(200); -/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(242); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(201); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); +/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(274); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(233); /** PURE_IMPORTS_START _Observable,_util_isScheduler,_operators_mergeAll,_fromArray PURE_IMPORTS_END */ @@ -24788,15 +31263,15 @@ function merge() { /***/ }), -/* 253 */ +/* 285 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return NEVER; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "never", function() { return never; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(180); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); /** PURE_IMPORTS_START _Observable,_util_noop PURE_IMPORTS_END */ @@ -24808,16 +31283,16 @@ function never() { /***/ }), -/* 254 */ +/* 286 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(172); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(267); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(230); /** PURE_IMPORTS_START _Observable,_from,_util_isArray,_empty PURE_IMPORTS_END */ @@ -24848,15 +31323,15 @@ function onErrorResumeNext() { /***/ }), -/* 255 */ +/* 287 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return pairs; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */ @@ -24899,7 +31374,7 @@ function dispatch(state) { /***/ }), -/* 256 */ +/* 288 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -24907,11 +31382,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceOperator", function() { return RaceOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceSubscriber", function() { return RaceSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(172); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(201); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(233); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_util_isArray,_fromArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -24993,14 +31468,14 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 257 */ +/* 289 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "range", function() { return range; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function range(start, count, scheduler) { @@ -25051,16 +31526,16 @@ function dispatch(state) { /***/ }), -/* 258 */ +/* 290 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(163); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(210); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(200); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(283); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(232); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -25105,15 +31580,15 @@ function dispatch(state) { /***/ }), -/* 259 */ +/* 291 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "using", function() { return using; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(267); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -25150,7 +31625,7 @@ function using(resourceFactory, observableFactory) { /***/ }), -/* 260 */ +/* 292 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -25158,13 +31633,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipOperator", function() { return ZipOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipSubscriber", function() { return ZipSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(201); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(172); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(165); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(225); -/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(230); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(197); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(257); +/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(262); /** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_OuterSubscriber,_util_subscribeToResult,_.._internal_symbol_iterator PURE_IMPORTS_END */ @@ -25384,320 +31859,320 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) { /***/ }), -/* 261 */ +/* 293 */ /***/ (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__(262); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(294); /* 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__(263); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); /* 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__(264); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(296); /* 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__(265); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(297); /* 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__(266); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(298); /* 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__(267); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(299); /* 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__(268); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(300); /* 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__(269); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(301); /* 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__(270); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(302); /* 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__(271); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(303); /* 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__(272); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(304); /* 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__(241); +/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(273); /* 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__(273); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(305); /* 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__(274); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(306); /* 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__(275); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(307); /* 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__(276); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(308); /* 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__(277); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(309); /* 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__(278); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(310); /* 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__(279); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(311); /* 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__(281); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(313); /* 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__(282); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(314); /* 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__(283); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(315); /* 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__(284); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(316); /* 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__(285); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(317); /* 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__(286); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(318); /* 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__(291); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(323); /* 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__(292); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(324); /* 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__(293); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(325); /* 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__(294); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(326); /* 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__(295); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(327); /* 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__(287); +/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(319); /* 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__(296); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(328); /* 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__(297); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(329); /* 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__(298); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(330); /* 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__(299); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(331); /* 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__(186); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(218); /* 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__(300); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(332); /* 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__(301); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(333); /* 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__(302); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(334); /* 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__(221); +/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(253); /* 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__(304); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(336); /* 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__(305); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(337); /* 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__(306); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(338); /* 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__(309); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(341); /* 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__(242); +/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(274); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__["mergeAll"]; }); -/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(243); +/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(275); /* 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 import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(310); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(342); /* 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__(311); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(343); /* 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__(312); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(344); /* 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__(313); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(345); /* 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__(196); +/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(228); /* 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__(314); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(346); /* 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__(315); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(347); /* 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__(316); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(348); /* 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__(318); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(350); /* 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__(319); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(351); /* 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__(320); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(352); /* 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__(321); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(353); /* 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__(322); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(354); /* 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__(323); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(355); /* 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__(307); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(339); /* 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__(324); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(356); /* 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__(325); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(357); /* 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__(326); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(358); /* 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__(327); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(359); /* 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__(185); +/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(217); /* 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__(328); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(360); /* 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__(329); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(361); /* 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__(308); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(340); /* 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__(330); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(362); /* 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__(331); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(363); /* 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__(332); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(364); /* 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__(333); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(365); /* 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__(334); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(366); /* 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__(335); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(367); /* 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__(336); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(368); /* 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__(337); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(369); /* 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__(338); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(370); /* 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__(339); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(371); /* 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__(341); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(373); /* 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__(342); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(374); /* 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__(343); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(375); /* 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__(290); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(322); /* 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__(303); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(335); /* 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__(344); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(376); /* 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__(345); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(377); /* 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__(289); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(321); /* 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__(346); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(378); /* 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__(347); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(379); /* 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__(288); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(320); /* 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__(348); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(380); /* 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__(349); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(381); /* 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__(350); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(382); /* 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__(351); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(383); /* 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__(352); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(384); /* 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__(353); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(385); /* 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__(354); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(386); /* 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__(355); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(387); /* 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__(356); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(388); /* 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__(357); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(389); /* 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__(358); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(390); /* 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__(359); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(391); /* 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__(360); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(392); /* 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 */ @@ -25809,17 +32284,17 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 262 */ +/* 294 */ /***/ (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__(166); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(175); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -25892,15 +32367,15 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 263 */ +/* 295 */ /***/ (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__(210); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(262); -/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294); +/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(290); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -25915,15 +32390,15 @@ function auditTime(duration, scheduler) { /***/ }), -/* 264 */ +/* 296 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -25964,14 +32439,14 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 265 */ +/* 297 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return bufferCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -26065,16 +32540,16 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 266 */ +/* 298 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return bufferTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(210); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(165); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(200); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(197); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(232); /** PURE_IMPORTS_START tslib,_scheduler_async,_Subscriber,_util_isScheduler PURE_IMPORTS_END */ @@ -26226,16 +32701,16 @@ function dispatchBufferClose(arg) { /***/ }), -/* 267 */ +/* 299 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return bufferToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); /** PURE_IMPORTS_START tslib,_Subscription,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */ @@ -26346,18 +32821,18 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 268 */ +/* 300 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(171); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(175); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -26443,15 +32918,15 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 269 */ +/* 301 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -26500,13 +32975,13 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 270 */ +/* 302 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return combineAll; }); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(223); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(255); /** PURE_IMPORTS_START _observable_combineLatest PURE_IMPORTS_END */ function combineAll(project) { @@ -26516,15 +32991,15 @@ function combineAll(project) { /***/ }), -/* 271 */ +/* 303 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(172); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(235); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(255); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(267); /** PURE_IMPORTS_START _util_isArray,_observable_combineLatest,_observable_from PURE_IMPORTS_END */ @@ -26548,13 +33023,13 @@ function combineLatest() { /***/ }), -/* 272 */ +/* 304 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(234); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(266); /** PURE_IMPORTS_START _observable_concat PURE_IMPORTS_END */ function concat() { @@ -26568,13 +33043,13 @@ function concat() { /***/ }), -/* 273 */ +/* 305 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return concatMap; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(243); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function concatMap(project, resultSelector) { @@ -26584,13 +33059,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 274 */ +/* 306 */ /***/ (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__(273); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(305); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -26600,14 +33075,14 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 275 */ +/* 307 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "count", function() { return count; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -26665,15 +33140,15 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 276 */ +/* 308 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -26753,15 +33228,15 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 277 */ +/* 309 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return debounceTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(210); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(242); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -26829,14 +33304,14 @@ function dispatchNext(subscriber) { /***/ }), -/* 278 */ +/* 310 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return defaultIfEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -26879,17 +33354,17 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 279 */ +/* 311 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(210); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(165); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(197); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(312); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(197); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(229); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -26983,7 +33458,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 280 */ +/* 312 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26997,17 +33472,17 @@ function isDate(value) { /***/ }), -/* 281 */ +/* 313 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return delayWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(163); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(195); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -27138,14 +33613,14 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 282 */ +/* 314 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return dematerialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -27176,16 +33651,16 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 283 */ +/* 315 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -27254,16 +33729,16 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 284 */ +/* 316 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return distinctUntilChanged; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(175); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); /** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */ @@ -27326,13 +33801,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 285 */ +/* 317 */ /***/ (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__(284); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(316); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -27342,17 +33817,17 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 286 */ +/* 318 */ /***/ (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__(217); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(288); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(290); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(249); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(319); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(320); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(310); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(322); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -27374,14 +33849,14 @@ function elementAt(index, defaultValue) { /***/ }), -/* 287 */ +/* 319 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return filter; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -27428,14 +33903,14 @@ var FilterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 288 */ +/* 320 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return throwIfEmpty; }); -/* harmony import */ var _tap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(289); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(218); +/* harmony import */ var _tap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(321); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(250); /** PURE_IMPORTS_START _tap,_util_EmptyError PURE_IMPORTS_END */ @@ -27460,16 +33935,16 @@ function defaultErrorFactory() { /***/ }), -/* 289 */ +/* 321 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return tap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(180); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(167); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(199); /** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */ @@ -27548,16 +34023,16 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 290 */ +/* 322 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "take", function() { return take; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(217); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(249); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(230); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -27610,17 +34085,17 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 291 */ +/* 323 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return endWith; }); -/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(201); -/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(234); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(200); +/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(233); +/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(266); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(232); /** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */ @@ -27656,14 +34131,14 @@ function endWith() { /***/ }), -/* 292 */ +/* 324 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "every", function() { return every; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -27718,15 +34193,15 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 293 */ +/* 325 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -27775,17 +34250,17 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 294 */ +/* 326 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(221); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(235); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(253); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(267); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ @@ -27861,7 +34336,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 295 */ +/* 327 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27869,11 +34344,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return expand; }); /* 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__(166); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(175); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -27977,15 +34452,15 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 296 */ +/* 328 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return finalize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(171); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(203); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription PURE_IMPORTS_END */ @@ -28015,7 +34490,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 297 */ +/* 329 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28023,8 +34498,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "find", function() { return find; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueOperator", function() { return FindValueOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueSubscriber", function() { return FindValueSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -28086,13 +34561,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 298 */ +/* 330 */ /***/ (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__(297); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(329); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -28102,18 +34577,18 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 299 */ +/* 331 */ /***/ (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__(218); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(290); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(288); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(215); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(250); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(319); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(322); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(310); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(320); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(247); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -28129,14 +34604,14 @@ function first(predicate, defaultValue) { /***/ }), -/* 300 */ +/* 332 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return ignoreElements; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -28166,14 +34641,14 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 301 */ +/* 333 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return isEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -28210,18 +34685,18 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 302 */ +/* 334 */ /***/ (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__(218); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(303); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(278); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(215); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(250); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(319); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(335); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(320); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(310); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(247); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -28237,16 +34712,16 @@ function last(predicate, defaultValue) { /***/ }), -/* 303 */ +/* 335 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return takeLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(217); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(249); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(230); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -28314,14 +34789,14 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 304 */ +/* 336 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return mapTo; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -28353,15 +34828,15 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 305 */ +/* 337 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return materialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(197); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(229); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -28403,13 +34878,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 306 */ +/* 338 */ /***/ (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__(307); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(339); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -28422,16 +34897,16 @@ function max(comparer) { /***/ }), -/* 307 */ +/* 339 */ /***/ (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__(308); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(303); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(278); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(179); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(340); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(335); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(211); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -28453,14 +34928,14 @@ function reduce(accumulator, seed) { /***/ }), -/* 308 */ +/* 340 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return scan; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -28535,13 +35010,13 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 309 */ +/* 341 */ /***/ (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__(252); +/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); /** PURE_IMPORTS_START _observable_merge PURE_IMPORTS_END */ function merge() { @@ -28555,13 +35030,13 @@ function merge() { /***/ }), -/* 310 */ +/* 342 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return mergeMapTo; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(243); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function mergeMapTo(innerObservable, resultSelector, concurrent) { @@ -28580,7 +35055,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 311 */ +/* 343 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28588,11 +35063,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return mergeScan; }); /* 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__(166); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(175); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(225); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(256); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */ @@ -28687,13 +35162,13 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 312 */ +/* 344 */ /***/ (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__(307); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(339); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -28706,14 +35181,14 @@ function min(comparer) { /***/ }), -/* 313 */ +/* 345 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return multicast; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MulticastOperator", function() { return MulticastOperator; }); -/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(181); +/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); /** PURE_IMPORTS_START _observable_ConnectableObservable PURE_IMPORTS_END */ function multicast(subjectOrSubjectFactory, selector) { @@ -28755,18 +35230,18 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 314 */ +/* 346 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNextStatic", function() { return onErrorResumeNextStatic; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(172); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(267); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -28839,14 +35314,14 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 315 */ +/* 347 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return pairwise; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -28883,14 +35358,14 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 316 */ +/* 348 */ /***/ (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__(317); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); +/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(349); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(319); /** PURE_IMPORTS_START _util_not,_filter PURE_IMPORTS_END */ @@ -28906,7 +35381,7 @@ function partition(predicate, thisArg) { /***/ }), -/* 317 */ +/* 349 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28925,13 +35400,13 @@ function not(pred, thisArg) { /***/ }), -/* 318 */ +/* 350 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return pluck; }); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(221); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(253); /** PURE_IMPORTS_START _map PURE_IMPORTS_END */ function pluck() { @@ -28965,14 +35440,14 @@ function plucker(props, length) { /***/ }), -/* 319 */ +/* 351 */ /***/ (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__(182); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(214); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(345); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -28985,14 +35460,14 @@ function publish(selector) { /***/ }), -/* 320 */ +/* 352 */ /***/ (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__(187); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313); +/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(219); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(345); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -29003,14 +35478,14 @@ function publishBehavior(value) { /***/ }), -/* 321 */ +/* 353 */ /***/ (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__(205); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(237); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(345); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -29021,14 +35496,14 @@ function publishLast() { /***/ }), -/* 322 */ +/* 354 */ /***/ (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__(188); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(220); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(345); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -29044,14 +35519,14 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 323 */ +/* 355 */ /***/ (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__(172); -/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(288); /** PURE_IMPORTS_START _util_isArray,_observable_race PURE_IMPORTS_END */ @@ -29071,15 +35546,15 @@ function race() { /***/ }), -/* 324 */ +/* 356 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return repeat; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); /** PURE_IMPORTS_START tslib,_Subscriber,_observable_empty PURE_IMPORTS_END */ @@ -29136,18 +35611,18 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 325 */ +/* 357 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(175); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -29232,14 +35707,14 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 326 */ +/* 358 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return retry; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -29285,18 +35760,18 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 327 */ +/* 359 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(175); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -29374,15 +35849,15 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 328 */ +/* 360 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -29431,15 +35906,15 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 329 */ +/* 361 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return sampleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(210); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(242); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -29491,7 +35966,7 @@ function dispatchNotification(state) { /***/ }), -/* 330 */ +/* 362 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29499,10 +35974,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return sequenceEqual; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualOperator", function() { return SequenceEqualOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualSubscriber", function() { return SequenceEqualSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(175); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); /** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */ @@ -29610,15 +36085,15 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 331 */ +/* 363 */ /***/ (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__(313); -/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(185); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(182); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(345); +/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(217); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(214); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -29633,13 +36108,13 @@ function share() { /***/ }), -/* 332 */ +/* 364 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return shareReplay; }); -/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(188); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(220); /** PURE_IMPORTS_START _ReplaySubject PURE_IMPORTS_END */ function shareReplay(bufferSize, windowTime, scheduler) { @@ -29682,15 +36157,15 @@ function shareReplayOperator(bufferSize, windowTime, scheduler) { /***/ }), -/* 333 */ +/* 365 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "single", function() { return single; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(218); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(250); /** PURE_IMPORTS_START tslib,_Subscriber,_util_EmptyError PURE_IMPORTS_END */ @@ -29762,14 +36237,14 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 334 */ +/* 366 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return skip; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -29804,15 +36279,15 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 335 */ +/* 367 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return skipLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(217); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(249); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError PURE_IMPORTS_END */ @@ -29866,15 +36341,15 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 336 */ +/* 368 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -29918,14 +36393,14 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 337 */ +/* 369 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return skipWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -29974,17 +36449,17 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 338 */ +/* 370 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return startWith; }); -/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(201); -/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(234); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(200); +/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(233); +/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(266); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(232); /** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */ @@ -30020,13 +36495,13 @@ function startWith() { /***/ }), -/* 339 */ +/* 371 */ /***/ (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__(340); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(372); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -30051,16 +36526,16 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 340 */ +/* 372 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubscribeOnObservable", function() { return SubscribeOnObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(163); -/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(251); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(195); +/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(238); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(283); /** PURE_IMPORTS_START tslib,_Observable,_scheduler_asap,_util_isNumeric PURE_IMPORTS_END */ @@ -30115,14 +36590,14 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 341 */ +/* 373 */ /***/ (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__(342); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(374); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(247); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -30133,17 +36608,17 @@ function switchAll() { /***/ }), -/* 342 */ +/* 374 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(221); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(235); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(253); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(267); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ @@ -30217,13 +36692,13 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 343 */ +/* 375 */ /***/ (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__(342); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(374); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -30233,15 +36708,15 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 344 */ +/* 376 */ /***/ (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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -30280,14 +36755,14 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 345 */ +/* 377 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return takeWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -30338,16 +36813,16 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 346 */ +/* 378 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -30442,16 +36917,16 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 347 */ +/* 379 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return throttleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(210); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(346); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(242); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(378); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -30536,17 +37011,17 @@ function dispatchNext(arg) { /***/ }), -/* 348 */ +/* 380 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(210); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(308); -/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(244); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(221); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(340); +/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(253); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -30580,16 +37055,16 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 349 */ +/* 381 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(210); -/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(219); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(350); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(204); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); +/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(382); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(236); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -30605,17 +37080,17 @@ function timeout(due, scheduler) { /***/ }), -/* 350 */ +/* 382 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(210); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(312); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -30687,15 +37162,15 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 351 */ +/* 383 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return timestamp; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Timestamp", function() { return Timestamp; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(210); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(221); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(253); /** PURE_IMPORTS_START _scheduler_async,_map PURE_IMPORTS_END */ @@ -30717,13 +37192,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 352 */ +/* 384 */ /***/ (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__(307); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(339); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -30740,16 +37215,16 @@ function toArray() { /***/ }), -/* 353 */ +/* 385 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -30820,15 +37295,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 354 */ +/* 386 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return windowCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(182); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(197); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(214); /** PURE_IMPORTS_START tslib,_Subscriber,_Subject PURE_IMPORTS_END */ @@ -30910,18 +37385,18 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 355 */ +/* 387 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return windowTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(210); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(165); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(251); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(200); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(242); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(197); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(283); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(232); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_async,_Subscriber,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -31080,19 +37555,19 @@ function dispatchWindowClose(state) { /***/ }), -/* 356 */ +/* 388 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return windowToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(171); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(175); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(203); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_Subject,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -31226,18 +37701,18 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 357 */ +/* 389 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return windowWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(182); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(174); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(175); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -31325,15 +37800,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 358 */ +/* 390 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return withLatestFrom; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -31420,13 +37895,13 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 359 */ +/* 391 */ /***/ (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__(260); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zip() { @@ -31442,13 +37917,13 @@ function zip() { /***/ }), -/* 360 */ +/* 392 */ /***/ (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__(260); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(292); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zipAll(project) { @@ -31458,7 +37933,7 @@ function zipAll(project) { /***/ }), -/* 361 */ +/* 393 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -31466,15 +37941,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(362); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(394); /* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(363); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(395); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(135); -/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(52); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(35); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(370); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(163); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(36); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(402); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -31552,7 +38027,7 @@ function toArray(value) { } /***/ }), -/* 362 */ +/* 394 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31586,13 +38061,13 @@ module.exports = (str, count, opts) => { /***/ }), -/* 363 */ +/* 395 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(364); -const stripAnsi = __webpack_require__(368); +const stringWidth = __webpack_require__(396); +const stripAnsi = __webpack_require__(400); const ESCAPES = new Set([ '\u001B', @@ -31786,13 +38261,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 364 */ +/* 396 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(365); -const isFullwidthCodePoint = __webpack_require__(367); +const stripAnsi = __webpack_require__(397); +const isFullwidthCodePoint = __webpack_require__(399); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -31829,18 +38304,18 @@ module.exports = str => { /***/ }), -/* 365 */ +/* 397 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(366); +const ansiRegex = __webpack_require__(398); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 366 */ +/* 398 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31857,7 +38332,7 @@ module.exports = () => { /***/ }), -/* 367 */ +/* 399 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31910,18 +38385,18 @@ module.exports = x => { /***/ }), -/* 368 */ +/* 400 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(369); +const ansiRegex = __webpack_require__(401); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 369 */ +/* 401 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31938,7 +38413,7 @@ module.exports = () => { /***/ }), -/* 370 */ +/* 402 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -32091,15 +38566,15 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 371 */ +/* 403 */ /***/ (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__(372); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(404); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(553); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(589); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -32124,23 +38599,23 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 372 */ +/* 404 */ /***/ (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__(373); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(405); /* 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__(137); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); /* 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__(16); /* 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__(135); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(163); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(54); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(35); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(55); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(36); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -32270,17 +38745,17 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 373 */ +/* 405 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const EventEmitter = __webpack_require__(45); +const EventEmitter = __webpack_require__(46); const path = __webpack_require__(16); -const arrify = __webpack_require__(374); -const globby = __webpack_require__(375); -const cpFile = __webpack_require__(544); -const CpyError = __webpack_require__(552); +const arrify = __webpack_require__(406); +const globby = __webpack_require__(407); +const cpFile = __webpack_require__(578); +const CpyError = __webpack_require__(588); const preprocessSrcPath = (srcPath, options) => options.cwd ? path.resolve(options.cwd, srcPath) : srcPath; @@ -32379,7 +38854,7 @@ module.exports = (src, dest, options = {}) => { /***/ }), -/* 374 */ +/* 406 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -32394,16 +38869,16 @@ module.exports = function (val) { /***/ }), -/* 375 */ +/* 407 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const arrayUnion = __webpack_require__(141); -const glob = __webpack_require__(36); -const fastGlob = __webpack_require__(376); -const dirGlob = __webpack_require__(539); -const gitignore = __webpack_require__(540); +const arrayUnion = __webpack_require__(169); +const glob = __webpack_require__(37); +const fastGlob = __webpack_require__(408); +const dirGlob = __webpack_require__(571); +const gitignore = __webpack_require__(574); const DEFAULT_FILTER = () => false; @@ -32529,10 +39004,10 @@ module.exports.gitignore = gitignore; /***/ }), -/* 376 */ +/* 408 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(377); +const pkg = __webpack_require__(409); module.exports = pkg.async; module.exports.default = pkg.async; @@ -32543,19 +39018,19 @@ module.exports.stream = pkg.stream; /***/ }), -/* 377 */ +/* 409 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(378); -var optionsManager = __webpack_require__(379); -var taskManager = __webpack_require__(380); -var reader_async_1 = __webpack_require__(518); -var reader_stream_1 = __webpack_require__(537); -var reader_sync_1 = __webpack_require__(538); -var arrayUtils = __webpack_require__(534); +var merge2 = __webpack_require__(410); +var optionsManager = __webpack_require__(411); +var taskManager = __webpack_require__(412); +var reader_async_1 = __webpack_require__(550); +var reader_stream_1 = __webpack_require__(569); +var reader_sync_1 = __webpack_require__(570); +var arrayUtils = __webpack_require__(566); /** * Returns a set of works based on provided tasks and class of the reader. */ @@ -32593,7 +39068,7 @@ exports.stream = stream; /***/ }), -/* 378 */ +/* 410 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -32707,7 +39182,7 @@ function pauseStreams (streams, options) { /***/ }), -/* 379 */ +/* 411 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -32742,14 +39217,14 @@ exports.prepare = prepare; /***/ }), -/* 380 */ +/* 412 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var objectUtils = __webpack_require__(381); -var patternUtils = __webpack_require__(382); +var objectUtils = __webpack_require__(413); +var patternUtils = __webpack_require__(414); /** * Returns grouped patterns by base directory of each pattern. */ @@ -32861,7 +39336,7 @@ exports.generate = generate; /***/ }), -/* 381 */ +/* 413 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -32874,7 +39349,7 @@ exports.values = values; /***/ }), -/* 382 */ +/* 414 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -32890,8 +39365,8 @@ var __values = (this && this.__values) || function (o) { }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var globParent = __webpack_require__(383); -var micromatch = __webpack_require__(387); +var globParent = __webpack_require__(415); +var micromatch = __webpack_require__(419); var GLOBSTAR = '**'; /** * Convert a windows «path» to a unix-style «path». @@ -33024,15 +39499,15 @@ exports.match = match; /***/ }), -/* 383 */ +/* 415 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(16); -var isglob = __webpack_require__(384); -var pathDirname = __webpack_require__(386); +var isglob = __webpack_require__(416); +var pathDirname = __webpack_require__(418); var isWin32 = __webpack_require__(11).platform() === 'win32'; module.exports = function globParent(str) { @@ -33055,7 +39530,7 @@ module.exports = function globParent(str) { /***/ }), -/* 384 */ +/* 416 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -33065,7 +39540,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(385); +var isExtglob = __webpack_require__(417); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -33086,7 +39561,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 385 */ +/* 417 */ /***/ (function(module, exports) { /*! @@ -33112,7 +39587,7 @@ module.exports = function isExtglob(str) { /***/ }), -/* 386 */ +/* 418 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -33262,7 +39737,7 @@ module.exports.win32 = win32; /***/ }), -/* 387 */ +/* 419 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -33273,18 +39748,18 @@ module.exports.win32 = win32; */ var util = __webpack_require__(29); -var braces = __webpack_require__(388); -var toRegex = __webpack_require__(389); -var extend = __webpack_require__(398); +var braces = __webpack_require__(420); +var toRegex = __webpack_require__(421); +var extend = __webpack_require__(430); /** * Local dependencies */ -var compilers = __webpack_require__(492); -var parsers = __webpack_require__(514); -var cache = __webpack_require__(515); -var utils = __webpack_require__(516); +var compilers = __webpack_require__(524); +var parsers = __webpack_require__(546); +var cache = __webpack_require__(547); +var utils = __webpack_require__(548); var MAX_LENGTH = 1024 * 64; /** @@ -34148,7 +40623,7 @@ module.exports = micromatch; /***/ }), -/* 388 */ +/* 420 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -34158,18 +40633,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(389); -var unique = __webpack_require__(401); -var extend = __webpack_require__(398); +var toRegex = __webpack_require__(421); +var unique = __webpack_require__(433); +var extend = __webpack_require__(430); /** * Local dependencies */ -var compilers = __webpack_require__(402); -var parsers = __webpack_require__(417); -var Braces = __webpack_require__(427); -var utils = __webpack_require__(403); +var compilers = __webpack_require__(434); +var parsers = __webpack_require__(449); +var Braces = __webpack_require__(459); +var utils = __webpack_require__(435); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -34473,15 +40948,15 @@ module.exports = braces; /***/ }), -/* 389 */ +/* 421 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(390); -var extend = __webpack_require__(398); -var not = __webpack_require__(400); +var define = __webpack_require__(422); +var extend = __webpack_require__(430); +var not = __webpack_require__(432); var MAX_LENGTH = 1024 * 64; /** @@ -34628,7 +41103,7 @@ module.exports.makeRe = makeRe; /***/ }), -/* 390 */ +/* 422 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -34641,7 +41116,7 @@ module.exports.makeRe = makeRe; -var isDescriptor = __webpack_require__(391); +var isDescriptor = __webpack_require__(423); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -34666,7 +41141,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 391 */ +/* 423 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -34679,9 +41154,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(392); -var isAccessor = __webpack_require__(393); -var isData = __webpack_require__(396); +var typeOf = __webpack_require__(424); +var isAccessor = __webpack_require__(425); +var isData = __webpack_require__(428); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -34695,7 +41170,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 392 */ +/* 424 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -34848,7 +41323,7 @@ function isBuffer(val) { /***/ }), -/* 393 */ +/* 425 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -34861,7 +41336,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(394); +var typeOf = __webpack_require__(426); // accessor descriptor properties var accessor = { @@ -34924,10 +41399,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 394 */ +/* 426 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(395); +var isBuffer = __webpack_require__(427); var toString = Object.prototype.toString; /** @@ -35046,7 +41521,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 395 */ +/* 427 */ /***/ (function(module, exports) { /*! @@ -35073,7 +41548,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 396 */ +/* 428 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35086,7 +41561,7 @@ function isSlowBuffer (obj) { -var typeOf = __webpack_require__(397); +var typeOf = __webpack_require__(429); // data descriptor properties var data = { @@ -35135,10 +41610,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 397 */ +/* 429 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(395); +var isBuffer = __webpack_require__(427); var toString = Object.prototype.toString; /** @@ -35257,13 +41732,13 @@ module.exports = function kindOf(val) { /***/ }), -/* 398 */ +/* 430 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(399); +var isObject = __webpack_require__(431); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -35297,7 +41772,7 @@ function hasOwn(obj, key) { /***/ }), -/* 399 */ +/* 431 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35317,13 +41792,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 400 */ +/* 432 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(398); +var extend = __webpack_require__(430); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -35390,7 +41865,7 @@ module.exports = toRegex; /***/ }), -/* 401 */ +/* 433 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -35440,13 +41915,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 402 */ +/* 434 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(403); +var utils = __webpack_require__(435); module.exports = function(braces, options) { braces.compiler @@ -35729,25 +42204,25 @@ function hasQueue(node) { /***/ }), -/* 403 */ +/* 435 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(404); +var splitString = __webpack_require__(436); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(398); -utils.flatten = __webpack_require__(410); -utils.isObject = __webpack_require__(408); -utils.fillRange = __webpack_require__(411); -utils.repeat = __webpack_require__(416); -utils.unique = __webpack_require__(401); +utils.extend = __webpack_require__(430); +utils.flatten = __webpack_require__(442); +utils.isObject = __webpack_require__(440); +utils.fillRange = __webpack_require__(443); +utils.repeat = __webpack_require__(448); +utils.unique = __webpack_require__(433); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -36079,7 +42554,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 404 */ +/* 436 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36092,7 +42567,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(405); +var extend = __webpack_require__(437); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -36257,14 +42732,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 405 */ +/* 437 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(406); -var assignSymbols = __webpack_require__(409); +var isExtendable = __webpack_require__(438); +var assignSymbols = __webpack_require__(441); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -36324,7 +42799,7 @@ function isEnum(obj, key) { /***/ }), -/* 406 */ +/* 438 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36337,7 +42812,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(407); +var isPlainObject = __webpack_require__(439); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -36345,7 +42820,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 407 */ +/* 439 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36358,7 +42833,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(408); +var isObject = __webpack_require__(440); function isObjectObject(o) { return isObject(o) === true @@ -36389,7 +42864,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 408 */ +/* 440 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36408,7 +42883,7 @@ module.exports = function isObject(val) { /***/ }), -/* 409 */ +/* 441 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36455,7 +42930,7 @@ module.exports = function(receiver, objects) { /***/ }), -/* 410 */ +/* 442 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36484,7 +42959,7 @@ function flat(arr, res) { /***/ }), -/* 411 */ +/* 443 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36498,10 +42973,10 @@ function flat(arr, res) { var util = __webpack_require__(29); -var isNumber = __webpack_require__(412); -var extend = __webpack_require__(398); -var repeat = __webpack_require__(414); -var toRegex = __webpack_require__(415); +var isNumber = __webpack_require__(444); +var extend = __webpack_require__(430); +var repeat = __webpack_require__(446); +var toRegex = __webpack_require__(447); /** * Return a range of numbers or letters. @@ -36699,7 +43174,7 @@ module.exports = fillRange; /***/ }), -/* 412 */ +/* 444 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36712,7 +43187,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(413); +var typeOf = __webpack_require__(445); module.exports = function isNumber(num) { var type = typeOf(num); @@ -36728,10 +43203,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 413 */ +/* 445 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(395); +var isBuffer = __webpack_require__(427); var toString = Object.prototype.toString; /** @@ -36850,7 +43325,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 414 */ +/* 446 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36927,7 +43402,7 @@ function repeat(str, num) { /***/ }), -/* 415 */ +/* 447 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -36940,8 +43415,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(414); -var isNumber = __webpack_require__(412); +var repeat = __webpack_require__(446); +var isNumber = __webpack_require__(444); var cache = {}; function toRegexRange(min, max, options) { @@ -37228,7 +43703,7 @@ module.exports = toRegexRange; /***/ }), -/* 416 */ +/* 448 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -37253,14 +43728,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 417 */ +/* 449 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(418); -var utils = __webpack_require__(403); +var Node = __webpack_require__(450); +var utils = __webpack_require__(435); /** * Braces parsers @@ -37620,15 +44095,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 418 */ +/* 450 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(408); -var define = __webpack_require__(419); -var utils = __webpack_require__(426); +var isObject = __webpack_require__(440); +var define = __webpack_require__(451); +var utils = __webpack_require__(458); var ownNames; /** @@ -38119,7 +44594,7 @@ exports = module.exports = Node; /***/ }), -/* 419 */ +/* 451 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38132,7 +44607,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(420); +var isDescriptor = __webpack_require__(452); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -38157,7 +44632,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 420 */ +/* 452 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38170,9 +44645,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(421); -var isAccessor = __webpack_require__(422); -var isData = __webpack_require__(424); +var typeOf = __webpack_require__(453); +var isAccessor = __webpack_require__(454); +var isData = __webpack_require__(456); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -38186,7 +44661,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 421 */ +/* 453 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -38321,7 +44796,7 @@ function isBuffer(val) { /***/ }), -/* 422 */ +/* 454 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38334,7 +44809,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(423); +var typeOf = __webpack_require__(455); // accessor descriptor properties var accessor = { @@ -38397,7 +44872,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 423 */ +/* 455 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -38532,7 +45007,7 @@ function isBuffer(val) { /***/ }), -/* 424 */ +/* 456 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38545,7 +45020,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(425); +var typeOf = __webpack_require__(457); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -38588,7 +45063,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 425 */ +/* 457 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -38723,13 +45198,13 @@ function isBuffer(val) { /***/ }), -/* 426 */ +/* 458 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(413); +var typeOf = __webpack_require__(445); var utils = module.exports; /** @@ -39749,17 +46224,17 @@ function assert(val, message) { /***/ }), -/* 427 */ +/* 459 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(398); -var Snapdragon = __webpack_require__(428); -var compilers = __webpack_require__(402); -var parsers = __webpack_require__(417); -var utils = __webpack_require__(403); +var extend = __webpack_require__(430); +var Snapdragon = __webpack_require__(460); +var compilers = __webpack_require__(434); +var parsers = __webpack_require__(449); +var utils = __webpack_require__(435); /** * Customize Snapdragon parser and renderer @@ -39860,17 +46335,17 @@ module.exports = Braces; /***/ }), -/* 428 */ +/* 460 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(429); -var define = __webpack_require__(390); -var Compiler = __webpack_require__(459); -var Parser = __webpack_require__(489); -var utils = __webpack_require__(469); +var Base = __webpack_require__(461); +var define = __webpack_require__(422); +var Compiler = __webpack_require__(491); +var Parser = __webpack_require__(521); +var utils = __webpack_require__(501); var regexCache = {}; var cache = {}; @@ -40041,20 +46516,20 @@ module.exports.Parser = Parser; /***/ }), -/* 429 */ +/* 461 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var define = __webpack_require__(430); -var CacheBase = __webpack_require__(431); -var Emitter = __webpack_require__(432); -var isObject = __webpack_require__(408); -var merge = __webpack_require__(450); -var pascal = __webpack_require__(453); -var cu = __webpack_require__(454); +var define = __webpack_require__(462); +var CacheBase = __webpack_require__(463); +var Emitter = __webpack_require__(464); +var isObject = __webpack_require__(440); +var merge = __webpack_require__(482); +var pascal = __webpack_require__(485); +var cu = __webpack_require__(486); /** * Optionally define a custom `cache` namespace to use. @@ -40483,7 +46958,7 @@ module.exports.namespace = namespace; /***/ }), -/* 430 */ +/* 462 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40496,7 +46971,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(420); +var isDescriptor = __webpack_require__(452); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -40521,21 +46996,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 431 */ +/* 463 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(408); -var Emitter = __webpack_require__(432); -var visit = __webpack_require__(433); -var toPath = __webpack_require__(436); -var union = __webpack_require__(437); -var del = __webpack_require__(441); -var get = __webpack_require__(439); -var has = __webpack_require__(446); -var set = __webpack_require__(449); +var isObject = __webpack_require__(440); +var Emitter = __webpack_require__(464); +var visit = __webpack_require__(465); +var toPath = __webpack_require__(468); +var union = __webpack_require__(469); +var del = __webpack_require__(473); +var get = __webpack_require__(471); +var has = __webpack_require__(478); +var set = __webpack_require__(481); /** * Create a `Cache` constructor that when instantiated will @@ -40789,7 +47264,7 @@ module.exports.namespace = namespace; /***/ }), -/* 432 */ +/* 464 */ /***/ (function(module, exports, __webpack_require__) { @@ -40958,7 +47433,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 433 */ +/* 465 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40971,8 +47446,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(434); -var mapVisit = __webpack_require__(435); +var visit = __webpack_require__(466); +var mapVisit = __webpack_require__(467); module.exports = function(collection, method, val) { var result; @@ -40995,7 +47470,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 434 */ +/* 466 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41008,7 +47483,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(408); +var isObject = __webpack_require__(440); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -41035,14 +47510,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 435 */ +/* 467 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(434); +var visit = __webpack_require__(466); /** * Map `visit` over an array of objects. @@ -41079,7 +47554,7 @@ function isObject(val) { /***/ }), -/* 436 */ +/* 468 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41092,7 +47567,7 @@ function isObject(val) { -var typeOf = __webpack_require__(413); +var typeOf = __webpack_require__(445); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -41119,16 +47594,16 @@ function filter(arr) { /***/ }), -/* 437 */ +/* 469 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(399); -var union = __webpack_require__(438); -var get = __webpack_require__(439); -var set = __webpack_require__(440); +var isObject = __webpack_require__(431); +var union = __webpack_require__(470); +var get = __webpack_require__(471); +var set = __webpack_require__(472); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -41156,7 +47631,7 @@ function arrayify(val) { /***/ }), -/* 438 */ +/* 470 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41192,7 +47667,7 @@ module.exports = function union(init) { /***/ }), -/* 439 */ +/* 471 */ /***/ (function(module, exports) { /*! @@ -41248,7 +47723,7 @@ function toString(val) { /***/ }), -/* 440 */ +/* 472 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41261,10 +47736,10 @@ function toString(val) { -var toPath = __webpack_require__(436); -var extend = __webpack_require__(398); -var isPlainObject = __webpack_require__(407); -var isObject = __webpack_require__(399); +var toPath = __webpack_require__(468); +var extend = __webpack_require__(430); +var isPlainObject = __webpack_require__(439); +var isObject = __webpack_require__(431); module.exports = function(obj, path, val) { if (!isObject(obj)) { @@ -41318,7 +47793,7 @@ module.exports = function(obj, path, val) { /***/ }), -/* 441 */ +/* 473 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41331,8 +47806,8 @@ module.exports = function(obj, path, val) { -var isObject = __webpack_require__(408); -var has = __webpack_require__(442); +var isObject = __webpack_require__(440); +var has = __webpack_require__(474); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -41357,7 +47832,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 442 */ +/* 474 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41370,9 +47845,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(443); -var hasValues = __webpack_require__(445); -var get = __webpack_require__(439); +var isObject = __webpack_require__(475); +var hasValues = __webpack_require__(477); +var get = __webpack_require__(471); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -41383,7 +47858,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 443 */ +/* 475 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41396,7 +47871,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(444); +var isArray = __webpack_require__(476); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -41404,7 +47879,7 @@ module.exports = function isObject(val) { /***/ }), -/* 444 */ +/* 476 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -41415,7 +47890,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 445 */ +/* 477 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41458,7 +47933,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 446 */ +/* 478 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41471,9 +47946,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(408); -var hasValues = __webpack_require__(447); -var get = __webpack_require__(439); +var isObject = __webpack_require__(440); +var hasValues = __webpack_require__(479); +var get = __webpack_require__(471); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -41481,7 +47956,7 @@ module.exports = function(val, prop) { /***/ }), -/* 447 */ +/* 479 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41494,8 +47969,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(448); -var isNumber = __webpack_require__(412); +var typeOf = __webpack_require__(480); +var isNumber = __webpack_require__(444); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -41548,10 +48023,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 448 */ +/* 480 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(395); +var isBuffer = __webpack_require__(427); var toString = Object.prototype.toString; /** @@ -41673,7 +48148,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 449 */ +/* 481 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41686,10 +48161,10 @@ module.exports = function kindOf(val) { -var split = __webpack_require__(404); -var extend = __webpack_require__(398); -var isPlainObject = __webpack_require__(407); -var isObject = __webpack_require__(399); +var split = __webpack_require__(436); +var extend = __webpack_require__(430); +var isPlainObject = __webpack_require__(439); +var isObject = __webpack_require__(431); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -41731,14 +48206,14 @@ module.exports = function(obj, prop, val) { /***/ }), -/* 450 */ +/* 482 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(451); -var forIn = __webpack_require__(452); +var isExtendable = __webpack_require__(483); +var forIn = __webpack_require__(484); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -41791,7 +48266,7 @@ module.exports = mixinDeep; /***/ }), -/* 451 */ +/* 483 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41804,7 +48279,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(407); +var isPlainObject = __webpack_require__(439); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -41812,7 +48287,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 452 */ +/* 484 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41835,7 +48310,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 453 */ +/* 485 */ /***/ (function(module, exports) { /*! @@ -41862,14 +48337,14 @@ module.exports = pascalcase; /***/ }), -/* 454 */ +/* 486 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(455); +var utils = __webpack_require__(487); /** * Expose class utils @@ -42234,7 +48709,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 455 */ +/* 487 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42248,10 +48723,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(438); -utils.define = __webpack_require__(390); -utils.isObj = __webpack_require__(408); -utils.staticExtend = __webpack_require__(456); +utils.union = __webpack_require__(470); +utils.define = __webpack_require__(422); +utils.isObj = __webpack_require__(440); +utils.staticExtend = __webpack_require__(488); /** @@ -42262,7 +48737,7 @@ module.exports = utils; /***/ }), -/* 456 */ +/* 488 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42275,8 +48750,8 @@ module.exports = utils; -var copy = __webpack_require__(457); -var define = __webpack_require__(390); +var copy = __webpack_require__(489); +var define = __webpack_require__(422); var util = __webpack_require__(29); /** @@ -42359,15 +48834,15 @@ module.exports = extend; /***/ }), -/* 457 */ +/* 489 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(413); -var copyDescriptor = __webpack_require__(458); -var define = __webpack_require__(390); +var typeOf = __webpack_require__(445); +var copyDescriptor = __webpack_require__(490); +var define = __webpack_require__(422); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -42540,7 +49015,7 @@ module.exports.has = has; /***/ }), -/* 458 */ +/* 490 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42628,16 +49103,16 @@ function isObject(val) { /***/ }), -/* 459 */ +/* 491 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(460); -var define = __webpack_require__(390); -var debug = __webpack_require__(462)('snapdragon:compiler'); -var utils = __webpack_require__(469); +var use = __webpack_require__(492); +var define = __webpack_require__(422); +var debug = __webpack_require__(494)('snapdragon:compiler'); +var utils = __webpack_require__(501); /** * Create a new `Compiler` with the given `options`. @@ -42791,7 +49266,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(488); + var sourcemaps = __webpack_require__(520); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -42812,7 +49287,7 @@ module.exports = Compiler; /***/ }), -/* 460 */ +/* 492 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42825,7 +49300,7 @@ module.exports = Compiler; -var utils = __webpack_require__(461); +var utils = __webpack_require__(493); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -42940,7 +49415,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 461 */ +/* 493 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42954,8 +49429,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(390); -utils.isObject = __webpack_require__(408); +utils.define = __webpack_require__(422); +utils.isObject = __webpack_require__(440); utils.isString = function(val) { @@ -42970,7 +49445,7 @@ module.exports = utils; /***/ }), -/* 462 */ +/* 494 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -42979,14 +49454,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(463); + module.exports = __webpack_require__(495); } else { - module.exports = __webpack_require__(466); + module.exports = __webpack_require__(498); } /***/ }), -/* 463 */ +/* 495 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -42995,7 +49470,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(464); +exports = module.exports = __webpack_require__(496); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -43177,7 +49652,7 @@ function localstorage() { /***/ }), -/* 464 */ +/* 496 */ /***/ (function(module, exports, __webpack_require__) { @@ -43193,7 +49668,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(465); +exports.humanize = __webpack_require__(497); /** * The currently active debug mode names, and names to skip. @@ -43385,7 +49860,7 @@ function coerce(val) { /***/ }), -/* 465 */ +/* 497 */ /***/ (function(module, exports) { /** @@ -43543,14 +50018,14 @@ function plural(ms, n, name) { /***/ }), -/* 466 */ +/* 498 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(467); +var tty = __webpack_require__(499); var util = __webpack_require__(29); /** @@ -43559,7 +50034,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(464); +exports = module.exports = __webpack_require__(496); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -43738,7 +50213,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(468); + var net = __webpack_require__(500); stream = new net.Socket({ fd: fd, readable: false, @@ -43797,19 +50272,19 @@ exports.enable(load()); /***/ }), -/* 467 */ +/* 499 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 468 */ +/* 500 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 469 */ +/* 501 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43819,9 +50294,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(398); -exports.SourceMap = __webpack_require__(470); -exports.sourceMapResolve = __webpack_require__(481); +exports.extend = __webpack_require__(430); +exports.SourceMap = __webpack_require__(502); +exports.sourceMapResolve = __webpack_require__(513); /** * Convert backslash in the given string to forward slashes @@ -43864,7 +50339,7 @@ exports.last = function(arr, n) { /***/ }), -/* 470 */ +/* 502 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -43872,13 +50347,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(471).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(477).SourceMapConsumer; -exports.SourceNode = __webpack_require__(480).SourceNode; +exports.SourceMapGenerator = __webpack_require__(503).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(509).SourceMapConsumer; +exports.SourceNode = __webpack_require__(512).SourceNode; /***/ }), -/* 471 */ +/* 503 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -43888,10 +50363,10 @@ exports.SourceNode = __webpack_require__(480).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(472); -var util = __webpack_require__(474); -var ArraySet = __webpack_require__(475).ArraySet; -var MappingList = __webpack_require__(476).MappingList; +var base64VLQ = __webpack_require__(504); +var util = __webpack_require__(506); +var ArraySet = __webpack_require__(507).ArraySet; +var MappingList = __webpack_require__(508).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -44300,7 +50775,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 472 */ +/* 504 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -44340,7 +50815,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(473); +var base64 = __webpack_require__(505); // 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, @@ -44446,7 +50921,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 473 */ +/* 505 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -44519,7 +50994,7 @@ exports.decode = function (charCode) { /***/ }), -/* 474 */ +/* 506 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -44942,7 +51417,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 475 */ +/* 507 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -44952,7 +51427,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(474); +var util = __webpack_require__(506); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -45069,7 +51544,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 476 */ +/* 508 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -45079,7 +51554,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(474); +var util = __webpack_require__(506); /** * Determine whether mappingB is after mappingA with respect to generated @@ -45154,7 +51629,7 @@ exports.MappingList = MappingList; /***/ }), -/* 477 */ +/* 509 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -45164,11 +51639,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(474); -var binarySearch = __webpack_require__(478); -var ArraySet = __webpack_require__(475).ArraySet; -var base64VLQ = __webpack_require__(472); -var quickSort = __webpack_require__(479).quickSort; +var util = __webpack_require__(506); +var binarySearch = __webpack_require__(510); +var ArraySet = __webpack_require__(507).ArraySet; +var base64VLQ = __webpack_require__(504); +var quickSort = __webpack_require__(511).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -46242,7 +52717,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 478 */ +/* 510 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -46359,7 +52834,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 479 */ +/* 511 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -46479,7 +52954,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 480 */ +/* 512 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -46489,8 +52964,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(471).SourceMapGenerator; -var util = __webpack_require__(474); +var SourceMapGenerator = __webpack_require__(503).SourceMapGenerator; +var util = __webpack_require__(506); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -46898,17 +53373,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 481 */ +/* 513 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(482) -var resolveUrl = __webpack_require__(483) -var decodeUriComponent = __webpack_require__(484) -var urix = __webpack_require__(486) -var atob = __webpack_require__(487) +var sourceMappingURL = __webpack_require__(514) +var resolveUrl = __webpack_require__(515) +var decodeUriComponent = __webpack_require__(516) +var urix = __webpack_require__(518) +var atob = __webpack_require__(519) @@ -47206,7 +53681,7 @@ module.exports = { /***/ }), -/* 482 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -47269,13 +53744,13 @@ void (function(root, factory) { /***/ }), -/* 483 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var url = __webpack_require__(74) +var url = __webpack_require__(82) function resolveUrl(/* ...urls */) { return Array.prototype.reduce.call(arguments, function(resolved, nextUrl) { @@ -47287,13 +53762,13 @@ module.exports = resolveUrl /***/ }), -/* 484 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(485) +var decodeUriComponent = __webpack_require__(517) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -47304,7 +53779,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 485 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47405,7 +53880,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 486 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -47428,7 +53903,7 @@ module.exports = urix /***/ }), -/* 487 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47442,7 +53917,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 488 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47450,8 +53925,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(390); -var utils = __webpack_require__(469); +var define = __webpack_require__(422); +var utils = __webpack_require__(501); /** * Expose `mixin()`. @@ -47594,19 +54069,19 @@ exports.comment = function(node) { /***/ }), -/* 489 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(460); +var use = __webpack_require__(492); var util = __webpack_require__(29); -var Cache = __webpack_require__(490); -var define = __webpack_require__(390); -var debug = __webpack_require__(462)('snapdragon:parser'); -var Position = __webpack_require__(491); -var utils = __webpack_require__(469); +var Cache = __webpack_require__(522); +var define = __webpack_require__(422); +var debug = __webpack_require__(494)('snapdragon:parser'); +var Position = __webpack_require__(523); +var utils = __webpack_require__(501); /** * Create a new `Parser` with the given `input` and `options`. @@ -48134,7 +54609,7 @@ module.exports = Parser; /***/ }), -/* 490 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48241,13 +54716,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 491 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(390); +var define = __webpack_require__(422); /** * Store position for a node @@ -48262,14 +54737,14 @@ module.exports = function Position(start, parser) { /***/ }), -/* 492 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(493); -var extglob = __webpack_require__(504); +var nanomatch = __webpack_require__(525); +var extglob = __webpack_require__(536); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -48346,7 +54821,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 493 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48357,17 +54832,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(29); -var toRegex = __webpack_require__(389); -var extend = __webpack_require__(398); +var toRegex = __webpack_require__(421); +var extend = __webpack_require__(430); /** * Local dependencies */ -var compilers = __webpack_require__(494); -var parsers = __webpack_require__(495); -var cache = __webpack_require__(497); -var utils = __webpack_require__(499); +var compilers = __webpack_require__(526); +var parsers = __webpack_require__(527); +var cache = __webpack_require__(529); +var utils = __webpack_require__(531); var MAX_LENGTH = 1024 * 64; /** @@ -49196,7 +55671,7 @@ module.exports = nanomatch; /***/ }), -/* 494 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49522,15 +55997,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 495 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(400); -var toRegex = __webpack_require__(389); -var isOdd = __webpack_require__(496); +var regexNot = __webpack_require__(432); +var toRegex = __webpack_require__(421); +var isOdd = __webpack_require__(528); /** * Characters to use in negation regex (we want to "not" match @@ -49917,7 +56392,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 496 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49930,7 +56405,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(412); +var isNumber = __webpack_require__(444); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -49944,14 +56419,14 @@ module.exports = function isOdd(i) { /***/ }), -/* 497 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(498))(); +module.exports = new (__webpack_require__(530))(); /***/ }), -/* 498 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49964,7 +56439,7 @@ module.exports = new (__webpack_require__(498))(); -var MapCache = __webpack_require__(490); +var MapCache = __webpack_require__(522); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -50086,7 +56561,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 499 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50099,13 +56574,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(428); -utils.define = __webpack_require__(500); -utils.diff = __webpack_require__(501); -utils.extend = __webpack_require__(398); -utils.pick = __webpack_require__(502); -utils.typeOf = __webpack_require__(503); -utils.unique = __webpack_require__(401); +var Snapdragon = __webpack_require__(460); +utils.define = __webpack_require__(532); +utils.diff = __webpack_require__(533); +utils.extend = __webpack_require__(430); +utils.pick = __webpack_require__(534); +utils.typeOf = __webpack_require__(535); +utils.unique = __webpack_require__(433); /** * Returns true if the given value is effectively an empty string @@ -50471,7 +56946,7 @@ utils.unixify = function(options) { /***/ }), -/* 500 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50484,7 +56959,7 @@ utils.unixify = function(options) { -var isDescriptor = __webpack_require__(420); +var isDescriptor = __webpack_require__(452); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -50509,7 +56984,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 501 */ +/* 533 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50563,7 +57038,7 @@ function diffArray(one, two) { /***/ }), -/* 502 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50576,7 +57051,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(408); +var isObject = __webpack_require__(440); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -50605,7 +57080,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 503 */ +/* 535 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -50758,7 +57233,7 @@ function isBuffer(val) { /***/ }), -/* 504 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50768,18 +57243,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(398); -var unique = __webpack_require__(401); -var toRegex = __webpack_require__(389); +var extend = __webpack_require__(430); +var unique = __webpack_require__(433); +var toRegex = __webpack_require__(421); /** * Local dependencies */ -var compilers = __webpack_require__(505); -var parsers = __webpack_require__(511); -var Extglob = __webpack_require__(513); -var utils = __webpack_require__(512); +var compilers = __webpack_require__(537); +var parsers = __webpack_require__(543); +var Extglob = __webpack_require__(545); +var utils = __webpack_require__(544); var MAX_LENGTH = 1024 * 64; /** @@ -51096,13 +57571,13 @@ module.exports = extglob; /***/ }), -/* 505 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(506); +var brackets = __webpack_require__(538); /** * Extglob compilers @@ -51272,7 +57747,7 @@ module.exports = function(extglob) { /***/ }), -/* 506 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51282,17 +57757,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(507); -var parsers = __webpack_require__(509); +var compilers = __webpack_require__(539); +var parsers = __webpack_require__(541); /** * Module dependencies */ -var debug = __webpack_require__(462)('expand-brackets'); -var extend = __webpack_require__(398); -var Snapdragon = __webpack_require__(428); -var toRegex = __webpack_require__(389); +var debug = __webpack_require__(494)('expand-brackets'); +var extend = __webpack_require__(430); +var Snapdragon = __webpack_require__(460); +var toRegex = __webpack_require__(421); /** * Parses the given POSIX character class `pattern` and returns a @@ -51490,13 +57965,13 @@ module.exports = brackets; /***/ }), -/* 507 */ +/* 539 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(508); +var posix = __webpack_require__(540); module.exports = function(brackets) { brackets.compiler @@ -51584,7 +58059,7 @@ module.exports = function(brackets) { /***/ }), -/* 508 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51613,14 +58088,14 @@ module.exports = { /***/ }), -/* 509 */ +/* 541 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(510); -var define = __webpack_require__(390); +var utils = __webpack_require__(542); +var define = __webpack_require__(422); /** * Text regex @@ -51839,14 +58314,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 510 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(389); -var regexNot = __webpack_require__(400); +var toRegex = __webpack_require__(421); +var regexNot = __webpack_require__(432); var cached; /** @@ -51880,15 +58355,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 511 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(506); -var define = __webpack_require__(500); -var utils = __webpack_require__(512); +var brackets = __webpack_require__(538); +var define = __webpack_require__(532); +var utils = __webpack_require__(544); /** * Characters to use in text regex (we want to "not" match @@ -52043,14 +58518,14 @@ module.exports = parsers; /***/ }), -/* 512 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(400); -var Cache = __webpack_require__(498); +var regex = __webpack_require__(432); +var Cache = __webpack_require__(530); /** * Utils @@ -52119,7 +58594,7 @@ utils.createRegex = function(str) { /***/ }), -/* 513 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52129,16 +58604,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(428); -var define = __webpack_require__(500); -var extend = __webpack_require__(398); +var Snapdragon = __webpack_require__(460); +var define = __webpack_require__(532); +var extend = __webpack_require__(430); /** * Local dependencies */ -var compilers = __webpack_require__(505); -var parsers = __webpack_require__(511); +var compilers = __webpack_require__(537); +var parsers = __webpack_require__(543); /** * Customize Snapdragon parser and renderer @@ -52204,16 +58679,16 @@ module.exports = Extglob; /***/ }), -/* 514 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(504); -var nanomatch = __webpack_require__(493); -var regexNot = __webpack_require__(400); -var toRegex = __webpack_require__(389); +var extglob = __webpack_require__(536); +var nanomatch = __webpack_require__(525); +var regexNot = __webpack_require__(432); +var toRegex = __webpack_require__(421); var not; /** @@ -52294,14 +58769,14 @@ function textRegex(pattern) { /***/ }), -/* 515 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(498))(); +module.exports = new (__webpack_require__(530))(); /***/ }), -/* 516 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52314,13 +58789,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(428); -utils.define = __webpack_require__(500); -utils.diff = __webpack_require__(501); -utils.extend = __webpack_require__(398); -utils.pick = __webpack_require__(502); -utils.typeOf = __webpack_require__(517); -utils.unique = __webpack_require__(401); +var Snapdragon = __webpack_require__(460); +utils.define = __webpack_require__(532); +utils.diff = __webpack_require__(533); +utils.extend = __webpack_require__(430); +utils.pick = __webpack_require__(534); +utils.typeOf = __webpack_require__(549); +utils.unique = __webpack_require__(433); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -52617,7 +59092,7 @@ utils.unixify = function(options) { /***/ }), -/* 517 */ +/* 549 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -52752,7 +59227,7 @@ function isBuffer(val) { /***/ }), -/* 518 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52768,8 +59243,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(519); -var reader_1 = __webpack_require__(532); +var readdir = __webpack_require__(551); +var reader_1 = __webpack_require__(564); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -52805,15 +59280,15 @@ exports.default = ReaderAsync; /***/ }), -/* 519 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(520); -const readdirAsync = __webpack_require__(528); -const readdirStream = __webpack_require__(531); +const readdirSync = __webpack_require__(552); +const readdirAsync = __webpack_require__(560); +const readdirStream = __webpack_require__(563); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -52897,7 +59372,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 520 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52905,11 +59380,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(521); +const DirectoryReader = __webpack_require__(553); let syncFacade = { - fs: __webpack_require__(526), - forEach: __webpack_require__(527), + fs: __webpack_require__(558), + forEach: __webpack_require__(559), sync: true }; @@ -52938,18 +59413,18 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 521 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const Readable = __webpack_require__(28).Readable; -const EventEmitter = __webpack_require__(45).EventEmitter; +const EventEmitter = __webpack_require__(46).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(522); -const stat = __webpack_require__(524); -const call = __webpack_require__(525); +const normalizeOptions = __webpack_require__(554); +const stat = __webpack_require__(556); +const call = __webpack_require__(557); /** * Asynchronously reads the contents of a directory and streams the results @@ -53325,14 +59800,14 @@ module.exports = DirectoryReader; /***/ }), -/* 522 */ +/* 554 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(523); +const globToRegExp = __webpack_require__(555); module.exports = normalizeOptions; @@ -53509,7 +59984,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 523 */ +/* 555 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -53646,13 +60121,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 524 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(525); +const call = __webpack_require__(557); module.exports = stat; @@ -53727,7 +60202,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 525 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53788,14 +60263,14 @@ function callOnce (fn) { /***/ }), -/* 526 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(525); +const call = __webpack_require__(557); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -53859,7 +60334,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 527 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53888,7 +60363,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 528 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53896,12 +60371,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(529); -const DirectoryReader = __webpack_require__(521); +const maybe = __webpack_require__(561); +const DirectoryReader = __webpack_require__(553); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(530), + forEach: __webpack_require__(562), async: true }; @@ -53943,7 +60418,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 529 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53970,7 +60445,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 530 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54006,7 +60481,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 531 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54014,11 +60489,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(521); +const DirectoryReader = __webpack_require__(553); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(530), + forEach: __webpack_require__(562), async: true }; @@ -54038,15 +60513,15 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 532 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(533); -var entry_1 = __webpack_require__(536); +var deep_1 = __webpack_require__(565); +var entry_1 = __webpack_require__(568); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -54112,15 +60587,15 @@ exports.default = Reader; /***/ }), -/* 533 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var arrayUtils = __webpack_require__(534); -var pathUtils = __webpack_require__(535); -var patternUtils = __webpack_require__(382); +var arrayUtils = __webpack_require__(566); +var pathUtils = __webpack_require__(567); +var patternUtils = __webpack_require__(414); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -54195,7 +60670,7 @@ exports.default = DeepFilter; /***/ }), -/* 534 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54218,7 +60693,7 @@ exports.max = max; /***/ }), -/* 535 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54236,13 +60711,13 @@ exports.isDotDirectory = isDotDirectory; /***/ }), -/* 536 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(382); +var patternUtils = __webpack_require__(414); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -54314,7 +60789,7 @@ exports.default = DeepFilter; /***/ }), -/* 537 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54331,8 +60806,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var readdir = __webpack_require__(519); -var reader_1 = __webpack_require__(532); +var readdir = __webpack_require__(551); +var reader_1 = __webpack_require__(564); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -54375,7 +60850,7 @@ exports.default = ReaderStream; /***/ }), -/* 538 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54391,8 +60866,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(519); -var reader_1 = __webpack_require__(532); +var readdir = __webpack_require__(551); +var reader_1 = __webpack_require__(564); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -54427,14 +60902,14 @@ exports.default = ReaderSync; /***/ }), -/* 539 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const arrify = __webpack_require__(374); -const pathType = __webpack_require__(63); +const arrify = __webpack_require__(406); +const pathType = __webpack_require__(572); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; const getPath = filepath => filepath[0] === '!' ? filepath.slice(1) : filepath; @@ -54482,17 +60957,157 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 540 */ +/* 572 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const fs = __webpack_require__(23); +const pify = __webpack_require__(573); + +function type(fn, fn2, fp) { + if (typeof fp !== 'string') { + return Promise.reject(new TypeError(`Expected a string, got ${typeof fp}`)); + } + + return pify(fs[fn])(fp) + .then(stats => stats[fn2]()) + .catch(err => { + if (err.code === 'ENOENT') { + return false; + } + + throw err; + }); +} + +function typeSync(fn, fn2, fp) { + if (typeof fp !== 'string') { + throw new TypeError(`Expected a string, got ${typeof fp}`); + } + + try { + return fs[fn](fp)[fn2](); + } catch (err) { + if (err.code === 'ENOENT') { + return false; + } + + throw err; + } +} + +exports.file = type.bind(null, 'stat', 'isFile'); +exports.dir = type.bind(null, 'stat', 'isDirectory'); +exports.symlink = type.bind(null, 'lstat', 'isSymbolicLink'); +exports.fileSync = typeSync.bind(null, 'statSync', 'isFile'); +exports.dirSync = typeSync.bind(null, 'statSync', 'isDirectory'); +exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); + + +/***/ }), +/* 573 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const processFn = (fn, opts) => function () { + const P = opts.promiseModule; + const args = new Array(arguments.length); + + for (let i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + + return new P((resolve, reject) => { + if (opts.errorFirst) { + args.push(function (err, result) { + if (opts.multiArgs) { + const results = new Array(arguments.length - 1); + + for (let i = 1; i < arguments.length; i++) { + results[i - 1] = arguments[i]; + } + + if (err) { + results.unshift(err); + reject(results); + } else { + resolve(results); + } + } else if (err) { + reject(err); + } else { + resolve(result); + } + }); + } else { + args.push(function (result) { + if (opts.multiArgs) { + const results = new Array(arguments.length - 1); + + for (let i = 0; i < arguments.length; i++) { + results[i] = arguments[i]; + } + + resolve(results); + } else { + resolve(result); + } + }); + } + + fn.apply(this, args); + }); +}; + +module.exports = (obj, opts) => { + opts = Object.assign({ + exclude: [/.+(Sync|Stream)$/], + errorFirst: true, + promiseModule: Promise + }, opts); + + const filter = key => { + const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); + return opts.include ? opts.include.some(match) : !opts.exclude.some(match); + }; + + let ret; + if (typeof obj === 'function') { + ret = function () { + if (opts.excludeMain) { + return obj.apply(this, arguments); + } + + return processFn(obj, opts).apply(this, arguments); + }; + } else { + ret = Object.create(Object.getPrototypeOf(obj)); + } + + for (const key in obj) { // eslint-disable-line guard-for-in + const x = obj[key]; + ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; + } + + return ret; +}; + + +/***/ }), +/* 574 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(376); -const gitIgnore = __webpack_require__(541); -const pify = __webpack_require__(542); -const slash = __webpack_require__(543); +const fastGlob = __webpack_require__(408); +const gitIgnore = __webpack_require__(575); +const pify = __webpack_require__(576); +const slash = __webpack_require__(577); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -54584,7 +61199,7 @@ module.exports.sync = o => { /***/ }), -/* 541 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55016,7 +61631,7 @@ typeof process !== 'undefined' && (process.env && process.env.IGNORE_TEST_WIN32 /***/ }), -/* 542 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55107,7 +61722,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 543 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55125,17 +61740,17 @@ module.exports = function (str) { /***/ }), -/* 544 */ +/* 578 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const fsConstants = __webpack_require__(23).constants; -const {Buffer} = __webpack_require__(545); -const CpFileError = __webpack_require__(547); -const fs = __webpack_require__(549); -const ProgressEmitter = __webpack_require__(551); +const {Buffer} = __webpack_require__(579); +const CpFileError = __webpack_require__(581); +const fs = __webpack_require__(583); +const ProgressEmitter = __webpack_require__(587); module.exports = (src, dest, opts) => { if (!src || !dest) { @@ -55285,11 +61900,11 @@ module.exports.sync = (src, dest, opts) => { /***/ }), -/* 545 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { /* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(546) +var buffer = __webpack_require__(580) var Buffer = buffer.Buffer // alternative to using Object.keys for old browsers @@ -55353,18 +61968,18 @@ SafeBuffer.allocUnsafeSlow = function (size) { /***/ }), -/* 546 */ +/* 580 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 547 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(548); +const NestedError = __webpack_require__(582); class CpFileError extends NestedError { constructor(message, nested) { @@ -55378,10 +61993,10 @@ module.exports = CpFileError; /***/ }), -/* 548 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(43); +var inherits = __webpack_require__(44); var NestedError = function (message, nested) { this.nested = nested; @@ -55432,15 +62047,15 @@ module.exports = NestedError; /***/ }), -/* 549 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(22); -const makeDir = __webpack_require__(91); -const pify = __webpack_require__(550); -const CpFileError = __webpack_require__(547); +const makeDir = __webpack_require__(584); +const pify = __webpack_require__(586); +const CpFileError = __webpack_require__(581); const fsP = pify(fs); @@ -55585,7 +62200,99 @@ if (fs.copyFileSync) { /***/ }), -/* 550 */ +/* 584 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const fs = __webpack_require__(23); +const path = __webpack_require__(16); +const pify = __webpack_require__(585); + +const defaults = { + mode: 0o777 & (~process.umask()), + fs +}; + +// https://github.com/nodejs/node/issues/8987 +// https://github.com/libuv/libuv/pull/1088 +const checkPath = pth => { + if (process.platform === 'win32') { + const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, '')); + + if (pathHasInvalidWinCharacters) { + const err = new Error(`Path contains invalid characters: ${pth}`); + err.code = 'EINVAL'; + throw err; + } + } +}; + +module.exports = (input, opts) => Promise.resolve().then(() => { + checkPath(input); + opts = Object.assign({}, defaults, opts); + + const mkdir = pify(opts.fs.mkdir); + const stat = pify(opts.fs.stat); + + const make = pth => { + return mkdir(pth, opts.mode) + .then(() => pth) + .catch(err => { + if (err.code === 'ENOENT') { + if (err.message.includes('null bytes') || path.dirname(pth) === pth) { + throw err; + } + + return make(path.dirname(pth)).then(() => make(pth)); + } + + return stat(pth) + .then(stats => stats.isDirectory() ? pth : Promise.reject()) + .catch(() => { + throw err; + }); + }); + }; + + return make(path.resolve(input)); +}); + +module.exports.sync = (input, opts) => { + checkPath(input); + opts = Object.assign({}, defaults, opts); + + const make = pth => { + try { + opts.fs.mkdirSync(pth, opts.mode); + } catch (err) { + if (err.code === 'ENOENT') { + if (err.message.includes('null bytes') || path.dirname(pth) === pth) { + throw err; + } + + make(path.dirname(pth)); + return make(pth); + } + + try { + if (!opts.fs.statSync(pth).isDirectory()) { + throw new Error('The path is not a directory'); + } + } catch (_) { + throw err; + } + } + + return pth; + }; + + return make(path.resolve(input)); +}; + + +/***/ }), +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55676,12 +62383,103 @@ module.exports = (obj, opts) => { /***/ }), -/* 551 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const EventEmitter = __webpack_require__(45); + +const processFn = (fn, opts) => function () { + const P = opts.promiseModule; + const args = new Array(arguments.length); + + for (let i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + + return new P((resolve, reject) => { + if (opts.errorFirst) { + args.push(function (err, result) { + if (opts.multiArgs) { + const results = new Array(arguments.length - 1); + + for (let i = 1; i < arguments.length; i++) { + results[i - 1] = arguments[i]; + } + + if (err) { + results.unshift(err); + reject(results); + } else { + resolve(results); + } + } else if (err) { + reject(err); + } else { + resolve(result); + } + }); + } else { + args.push(function (result) { + if (opts.multiArgs) { + const results = new Array(arguments.length - 1); + + for (let i = 0; i < arguments.length; i++) { + results[i] = arguments[i]; + } + + resolve(results); + } else { + resolve(result); + } + }); + } + + fn.apply(this, args); + }); +}; + +module.exports = (obj, opts) => { + opts = Object.assign({ + exclude: [/.+(Sync|Stream)$/], + errorFirst: true, + promiseModule: Promise + }, opts); + + const filter = key => { + const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); + return opts.include ? opts.include.some(match) : !opts.exclude.some(match); + }; + + let ret; + if (typeof obj === 'function') { + ret = function () { + if (opts.excludeMain) { + return obj.apply(this, arguments); + } + + return processFn(obj, opts).apply(this, arguments); + }; + } else { + ret = Object.create(Object.getPrototypeOf(obj)); + } + + for (const key in obj) { // eslint-disable-line guard-for-in + const x = obj[key]; + ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; + } + + return ret; +}; + + +/***/ }), +/* 587 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const EventEmitter = __webpack_require__(46); const written = new WeakMap(); @@ -55717,12 +62515,12 @@ module.exports = ProgressEmitter; /***/ }), -/* 552 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(548); +const NestedError = __webpack_require__(582); class CpyError extends NestedError { constructor(message, nested) { @@ -55736,14 +62534,14 @@ module.exports = CpyError; /***/ }), -/* 553 */ +/* 589 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return prepareExternalProjectDependencies; }); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54); -/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(54); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 6927e43cd4d2a..70adf5c43939d 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -10,11 +10,11 @@ "prettier": "prettier --write './src/**/*.ts'" }, "devDependencies": { - "@babel/core": "7.4.5", - "@babel/plugin-proposal-class-properties": "7.4.4", - "@babel/plugin-proposal-object-rest-spread": "7.4.4", - "@babel/preset-env": "7.4.5", - "@babel/preset-typescript": "7.3.3", + "@babel/core": "^7.5.5", + "@babel/plugin-proposal-class-properties": "^7.5.5", + "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/preset-env": "^7.5.5", + "@babel/preset-typescript": "^7.3.3", "@types/cmd-shim": "^2.0.0", "@types/cpy": "^5.1.0", "@types/dedent": "^0.7.0", @@ -30,18 +30,18 @@ "@types/ncp": "^2.0.1", "@types/node": "^10.12.27", "@types/ora": "^1.3.2", - "@types/read-pkg": "^3.0.0", + "@types/read-pkg": "^4.0.0", "@types/strip-ansi": "^3.0.0", "@types/strong-log-transformer": "^1.0.0", "@types/tempy": "^0.2.0", - "@types/wrap-ansi": "^2.0.14", + "@types/wrap-ansi": "^2.0.15", "@types/write-pkg": "^3.1.0", - "babel-loader": "8.0.6", - "chalk": "^2.4.1", - "cmd-shim": "^2.0.2", + "babel-loader": "^8.0.6", + "chalk": "^2.4.2", + "cmd-shim": "^2.1.0", "cpy": "^7.0.1", "dedent": "^0.7.0", - "del": "^4.0.0", + "del": "^4.1.1", "execa": "^1.0.0", "getopts": "^2.2.4", "glob": "^7.1.2", @@ -54,19 +54,19 @@ "ncp": "^2.0.0", "ora": "^1.4.0", "prettier": "^1.14.3", - "read-pkg": "^3.0.0", + "read-pkg": "^5.2.0", "rxjs": "^6.2.1", "spawn-sync": "^1.0.15", - "string-replace-loader": "^2.1.1", + "string-replace-loader": "^2.2.0", "strip-ansi": "^4.0.0", "strong-log-transformer": "^2.1.0", "tempy": "^0.3.0", "typescript": "3.5.3", "unlazy-loader": "^0.1.3", - "webpack": "^4.23.1", - "webpack-cli": "^3.1.2", + "webpack": "^4.39.2", + "webpack-cli": "^3.3.7", "wrap-ansi": "^3.0.1", - "write-pkg": "^3.1.0" + "write-pkg": "^4.0.0" }, "dependencies": { "tslib": "^1.9.3" diff --git a/packages/kbn-pm/src/utils/package_json.ts b/packages/kbn-pm/src/utils/package_json.ts index c865b8e0c1a3d..a1bf1d18ee620 100644 --- a/packages/kbn-pm/src/utils/package_json.ts +++ b/packages/kbn-pm/src/utils/package_json.ts @@ -30,8 +30,8 @@ export interface IPackageScripts { [key: string]: string; } -export function readPackageJson(dir: string) { - return readPkg(dir, { normalize: false }); +export function readPackageJson(cwd: string): IPackageJson { + return readPkg({ cwd, normalize: false }); } export function writePackageJson(path: string, json: IPackageJson) { diff --git a/packages/kbn-pm/src/utils/workspaces.ts b/packages/kbn-pm/src/utils/workspaces.ts index cf06ca9e5df09..1cc5c5838989f 100644 --- a/packages/kbn-pm/src/utils/workspaces.ts +++ b/packages/kbn-pm/src/utils/workspaces.ts @@ -29,7 +29,7 @@ import { getProjects } from './projects'; const glob = promisify(globSync); export async function workspacePackagePaths(rootPath: string): Promise { - const rootPkgJson = await readPackageJson(path.join(rootPath, 'package.json')); + const rootPkgJson = await readPackageJson(rootPath); if (!rootPkgJson.workspaces) { return []; diff --git a/packages/kbn-pm/webpack.config.js b/packages/kbn-pm/webpack.config.js index ff77d3cfb7e9c..c86eb90128039 100644 --- a/packages/kbn-pm/webpack.config.js +++ b/packages/kbn-pm/webpack.config.js @@ -87,6 +87,12 @@ module.exports = { __dirname: false, }, + externals: { + worker_threads: { + commonjs: 'worker_threads', + }, + }, + watchOptions: { ignored: [/node_modules/, /vendor/], }, diff --git a/packages/kbn-spec-to-console/lib/convert.js b/packages/kbn-spec-to-console/lib/convert.js index 876f61ba0112c..4c31281860767 100644 --- a/packages/kbn-spec-to-console/lib/convert.js +++ b/packages/kbn-spec-to-console/lib/convert.js @@ -17,7 +17,6 @@ * under the License. */ - const convertParams = require('./convert/params'); const convertMethods = require('./convert/methods'); const convertPaths = require('./convert/paths'); @@ -25,38 +24,54 @@ const convertParts = require('./convert/parts'); module.exports = spec => { const result = {}; + // TODO: + // Since https://github.com/elastic/elasticsearch/pull/42346 has been merged into ES master + // the JSON doc specification has been updated. We need to update this script to take advantage + // of the added information but it will also require updating console's editor autocomplete. Object.keys(spec).forEach(api => { const source = spec[api]; if (!source.url) { return result; } - const convertedSpec = result[api] = {}; - if (source.url && source.url.params) { - const urlParams = convertParams(source.url.params); + const convertedSpec = (result[api] = {}); + if (source.params) { + const urlParams = convertParams(source.params); if (Object.keys(urlParams).length > 0) { convertedSpec.url_params = urlParams; } } - if (source.methods) { - convertedSpec.methods = convertMethods(source.methods); - } + const methodSet = new Set(); + let patterns; + const urlComponents = {}; if (source.url.paths) { - convertedSpec.patterns = convertPaths(source.url.paths); + patterns = convertPaths(source.url.paths); + source.url.paths.forEach(pathsObject => { + pathsObject.methods.forEach(method => methodSet.add(method)); + if (pathsObject.parts) { + for (const partName of Object.keys(pathsObject.parts)) { + urlComponents[partName] = pathsObject.parts[partName]; + } + } + }); } - if (source.url.parts) { - const components = convertParts(source.url.parts); - const hasComponents = Object.keys(components).filter(c => { - return Boolean(components[c]); - }).length > 0; + convertedSpec.methods = convertMethods(Array.from(methodSet)); + convertedSpec.patterns = patterns; + + if (Object.keys(urlComponents).length) { + const components = convertParts(urlComponents); + const hasComponents = + Object.keys(components).filter(c => { + return Boolean(components[c]); + }).length > 0; if (hasComponents) { - convertedSpec.url_components = convertParts(source.url.parts); + convertedSpec.url_components = convertParts(urlComponents); } } - if (source.documentation) { - convertedSpec.documentation = source.documentation; + if (source.documentation && source.documentation.url) { + convertedSpec.documentation = source.documentation.url; } }); diff --git a/packages/kbn-spec-to-console/lib/convert/parts.js b/packages/kbn-spec-to-console/lib/convert/parts.js index 51bb78668fa3c..040d04a0c1dc4 100644 --- a/packages/kbn-spec-to-console/lib/convert/parts.js +++ b/packages/kbn-spec-to-console/lib/convert/parts.js @@ -17,7 +17,6 @@ * under the License. */ - const replacePattern = require('../replace_pattern'); module.exports = parts => { diff --git a/packages/kbn-spec-to-console/lib/convert/paths.js b/packages/kbn-spec-to-console/lib/convert/paths.js index 90f6b885a185b..6c65bf48b9b06 100644 --- a/packages/kbn-spec-to-console/lib/convert/paths.js +++ b/packages/kbn-spec-to-console/lib/convert/paths.js @@ -17,11 +17,10 @@ * under the License. */ - const replacePattern = require('../replace_pattern'); module.exports = patterns => { - return patterns.map(pattern => { - return replacePattern(pattern, { brackets: true }); + return patterns.map(patternObject => { + return replacePattern(patternObject.path, { brackets: true }); }); }; diff --git a/packages/kbn-spec-to-console/lib/replace_pattern.js b/packages/kbn-spec-to-console/lib/replace_pattern.js index 244474c86a91f..29d16be3cc70f 100644 --- a/packages/kbn-spec-to-console/lib/replace_pattern.js +++ b/packages/kbn-spec-to-console/lib/replace_pattern.js @@ -17,7 +17,6 @@ * under the License. */ - const map = require('./static/map_interpolation'); module.exports = (pattern, { brackets, exact } = {}) => { diff --git a/packages/kbn-spec-to-console/test/fixtures/cluster_health_autocomplete.json b/packages/kbn-spec-to-console/test/fixtures/cluster_health_autocomplete.json index db1c19443a496..64ede603c0e0d 100644 --- a/packages/kbn-spec-to-console/test/fixtures/cluster_health_autocomplete.json +++ b/packages/kbn-spec-to-console/test/fixtures/cluster_health_autocomplete.json @@ -1,6 +1,12 @@ { "cluster.health": { "url_params": { + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ], "level": [ "cluster", "indices", @@ -34,6 +40,6 @@ "_cluster/health", "_cluster/health/{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-health.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-health.html" } } diff --git a/packages/kbn-spec-to-console/test/fixtures/cluster_health_spec.json b/packages/kbn-spec-to-console/test/fixtures/cluster_health_spec.json index ee32a87c927ed..7911a8e244218 100644 --- a/packages/kbn-spec-to-console/test/fixtures/cluster_health_spec.json +++ b/packages/kbn-spec-to-console/test/fixtures/cluster_health_spec.json @@ -1,64 +1,104 @@ { - "cluster.health": { - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-health.html", - "methods": ["GET"], - "url": { - "path": "/_cluster/health", - "paths": ["/_cluster/health", "/_cluster/health/{index}"], - "parts": { - "index": { - "type" : "list", - "description" : "Limit the information returned to a specific index" - } - }, - "params": { - "level": { - "type" : "enum", - "options" : ["cluster","indices","shards"], - "default" : "cluster", - "description" : "Specify the level of detail for returned information" - }, - "local": { - "type" : "boolean", - "description" : "Return local information, do not retrieve the state from master node (default: false)" - }, - "master_timeout": { - "type" : "time", - "description" : "Explicit operation timeout for connection to master node" - }, - "timeout": { - "type" : "time", - "description" : "Explicit operation timeout" - }, - "wait_for_active_shards": { - "type" : "string", - "description" : "Wait until the specified number of shards is active" - }, - "wait_for_nodes": { - "type" : "string", - "description" : "Wait until the specified number of nodes is available" - }, - "wait_for_events": { - "type" : "enum", - "options" : ["immediate", "urgent", "high", "normal", "low", "languid"], - "description" : "Wait until all currently queued events with the given priority are processed" - }, - "wait_for_no_relocating_shards": { - "type" : "boolean", - "description" : "Whether to wait until there are no relocating shards in the cluster" - }, - "wait_for_no_initializing_shards": { - "type" : "boolean", - "description" : "Whether to wait until there are no initializing shards in the cluster" + "cluster.health":{ + "documentation":{ + "url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-health.html", + "description":"Returns basic information about the health of the cluster." + }, + "stability":"stable", + "url":{ + "paths":[ + { + "path":"/_cluster/health", + "methods":[ + "GET" + ] }, - "wait_for_status": { - "type" : "enum", - "options" : ["green","yellow","red"], - "default" : null, - "description" : "Wait until cluster is in a specific state" + { + "path":"/_cluster/health/{index}", + "methods":[ + "GET" + ], + "parts":{ + "index":{ + "type":"list", + "description":"Limit the information returned to a specific index" + } + } } - } + ] }, - "body": null + "params":{ + "expand_wildcards":{ + "type":"enum", + "options":[ + "open", + "closed", + "none", + "all" + ], + "default":"all", + "description":"Whether to expand wildcard expression to concrete indices that are open, closed or both." + }, + "level":{ + "type":"enum", + "options":[ + "cluster", + "indices", + "shards" + ], + "default":"cluster", + "description":"Specify the level of detail for returned information" + }, + "local":{ + "type":"boolean", + "description":"Return local information, do not retrieve the state from master node (default: false)" + }, + "master_timeout":{ + "type":"time", + "description":"Explicit operation timeout for connection to master node" + }, + "timeout":{ + "type":"time", + "description":"Explicit operation timeout" + }, + "wait_for_active_shards":{ + "type":"string", + "description":"Wait until the specified number of shards is active" + }, + "wait_for_nodes":{ + "type":"string", + "description":"Wait until the specified number of nodes is available" + }, + "wait_for_events":{ + "type":"enum", + "options":[ + "immediate", + "urgent", + "high", + "normal", + "low", + "languid" + ], + "description":"Wait until all currently queued events with the given priority are processed" + }, + "wait_for_no_relocating_shards":{ + "type":"boolean", + "description":"Whether to wait until there are no relocating shards in the cluster" + }, + "wait_for_no_initializing_shards":{ + "type":"boolean", + "description":"Whether to wait until there are no initializing shards in the cluster" + }, + "wait_for_status":{ + "type":"enum", + "options":[ + "green", + "yellow", + "red" + ], + "default":null, + "description":"Wait until cluster is in a specific state" + } + } } } diff --git a/packages/kbn-test-subj-selector/__tests__/index.js b/packages/kbn-test-subj-selector/__tests__/index.js new file mode 100755 index 0000000000000..e18405b99ae52 --- /dev/null +++ b/packages/kbn-test-subj-selector/__tests__/index.js @@ -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. + */ + +const testSubjSelector = require('../'); +const expect = require('@kbn/expect'); + +describe('testSubjSelector()', function() { + it('converts subjectSelectors to cssSelectors', function() { + expect(testSubjSelector('foo bar')).to.eql('[data-test-subj="foo bar"]'); + expect(testSubjSelector('foo > bar')).to.eql('[data-test-subj="foo"] [data-test-subj="bar"]'); + expect(testSubjSelector('foo > bar baz')).to.eql( + '[data-test-subj="foo"] [data-test-subj="bar baz"]' + ); + expect(testSubjSelector('foo> ~bar')).to.eql('[data-test-subj="foo"] [data-test-subj~="bar"]'); + expect(testSubjSelector('~ foo')).to.eql('[data-test-subj~="foo"]'); + expect(testSubjSelector('~foo & ~ bar')).to.eql( + '[data-test-subj~="foo"][data-test-subj~="bar"]' + ); + }); +}); diff --git a/packages/kbn-test-subj-selector/index.js b/packages/kbn-test-subj-selector/index.js index 317f8eca46335..3984c15c00fef 100755 --- a/packages/kbn-test-subj-selector/index.js +++ b/packages/kbn-test-subj-selector/index.js @@ -19,12 +19,20 @@ function selectorToTerms(selector) { return selector - .replace(/\s*&\s*/g, '&') // remove all whitespace around joins - .split(/\s+/); + .replace(/\s*~\s*/g, '~') // css locator with '~' operator cannot contain spaces + .replace(/\s*>\s*/g, '>') // remove all whitespace around joins > + .replace(/\s*&\s*/g, '&') // remove all whitespace around joins & + .split(/>+/); } function termToCssSelector(term) { - return term ? '[data-test-subj~="' + term + '"]' : ''; + if (term) { + return term.startsWith('~') + ? '[data-test-subj~="' + term.substring(1).replace(/\s/g, '') + '"]' + : '[data-test-subj="' + term + '"]'; + } else { + return ''; + } } module.exports = function testSubjSelector(selector) { diff --git a/packages/kbn-test-subj-selector/package.json b/packages/kbn-test-subj-selector/package.json index f93245fd08848..82a26dc4807be 100755 --- a/packages/kbn-test-subj-selector/package.json +++ b/packages/kbn-test-subj-selector/package.json @@ -3,14 +3,7 @@ "version": "0.2.1", "description": "", "main": "index.js", - "scripts": { - "test": "mocha test" - }, "keywords": [], "author": "Spencer Alger ", - "license": "Apache-2.0", - "devDependencies": { - "@kbn/expect": "1.0.0", - "mocha": "^2.3.4" - } + "license": "Apache-2.0" } diff --git a/packages/kbn-test-subj-selector/test/index.js b/packages/kbn-test-subj-selector/test/index.js deleted file mode 100755 index c5a3826d19479..0000000000000 --- a/packages/kbn-test-subj-selector/test/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. - */ - -const testSubjSelector = require('../'); -const expect = require('@kbn/expect'); - -describe('testSubjSelector()', function() { - it('converts subjectSelectors to cssSelectors', function() { - expect(testSubjSelector('foo bar')).to.eql('[data-test-subj~="foo"] [data-test-subj~="bar"]'); - expect(testSubjSelector('foo&bar')).to.eql('[data-test-subj~="foo"][data-test-subj~="bar"]'); - expect(testSubjSelector('foo & bar')).to.eql('[data-test-subj~="foo"][data-test-subj~="bar"]'); - }); -}); diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index c38083317f3d1..6891f01bae2a9 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -5,19 +5,19 @@ "license": "Apache-2.0", "private": true, "scripts": { - "build": "babel src --out-dir target --delete-dir-on-start --extensions .ts,.js,.tsx", + "build": "babel src --out-dir target --delete-dir-on-start --extensions .ts,.js,.tsx --ignore *.test.js,**/__tests__/**", "kbn:bootstrap": "yarn build", "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "7.4.4", + "@babel/cli": "^7.5.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0" }, "dependencies": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "dedent": "^0.7.0", - "del": "^4.0.0", + "del": "^4.1.1", "getopts": "^2.2.4", "glob": "^7.1.2", "rxjs": "^6.2.1", diff --git a/packages/kbn-test/src/es/es_test_cluster.js b/packages/kbn-test/src/es/es_test_cluster.js index d1aa255914467..eb8373eb2206a 100644 --- a/packages/kbn-test/src/es/es_test_cluster.js +++ b/packages/kbn-test/src/es/es_test_cluster.js @@ -54,6 +54,7 @@ export function createEsTestCluster(options = {}) { basePath, esArgs, }; + const transportPort = esTestConfig.getTransportPort(); const cluster = new Cluster({ log, ssl }); @@ -88,6 +89,7 @@ export function createEsTestCluster(options = {}) { `cluster.name=${clusterName}`, `http.port=${port}`, 'discovery.type=single-node', + `transport.port=${transportPort}`, ...esArgs, ], esEnvVars, diff --git a/packages/kbn-test/src/es/es_test_config.js b/packages/kbn-test/src/es/es_test_config.js index 76282098119f4..d1d2b050c6467 100644 --- a/packages/kbn-test/src/es/es_test_config.js +++ b/packages/kbn-test/src/es/es_test_config.js @@ -38,6 +38,10 @@ export const esTestConfig = new (class EsTestConfig { return process.env.TEST_ES_FROM || 'snapshot'; } + getTransportPort() { + return process.env.TEST_ES_TRANSPORT_PORT || '9300-9400'; + } + getUrlParts() { // Allow setting one complete TEST_ES_URL for Es like https://elastic:changeme@myCloudInstance:9200 if (process.env.TEST_ES_URL) { diff --git a/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js b/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js index 711ce683ffdf7..3c8daf4154236 100644 --- a/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js +++ b/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js @@ -21,9 +21,10 @@ import { spawnSync } from 'child_process'; import { resolve } from 'path'; import expect from '@kbn/expect'; +import { REPO_ROOT } from '@kbn/dev-utils'; -const SCRIPT = resolve(__dirname, '../../../../scripts/functional_test_runner.js'); -const BASIC_CONFIG = resolve(__dirname, '../fixtures/simple_project/config.js'); +const SCRIPT = resolve(REPO_ROOT, 'scripts/functional_test_runner.js'); +const BASIC_CONFIG = require.resolve('../fixtures/simple_project/config.js'); describe('basic config file with a single app and test', function() { this.timeout(60 * 1000); diff --git a/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js b/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js index 08e71e2e73245..d6e7b1ac58aa4 100644 --- a/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js +++ b/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js @@ -22,9 +22,10 @@ import { resolve } from 'path'; import stripAnsi from 'strip-ansi'; import expect from '@kbn/expect'; +import { REPO_ROOT } from '@kbn/dev-utils'; -const SCRIPT = resolve(__dirname, '../../../../scripts/functional_test_runner.js'); -const FAILURE_HOOKS_CONFIG = resolve(__dirname, '../fixtures/failure_hooks/config.js'); +const SCRIPT = resolve(REPO_ROOT, 'scripts/functional_test_runner.js'); +const FAILURE_HOOKS_CONFIG = require.resolve('../fixtures/failure_hooks/config.js'); describe('failure hooks', function() { this.timeout(60 * 1000); diff --git a/packages/kbn-test/src/functional_test_runner/cli.ts b/packages/kbn-test/src/functional_test_runner/cli.ts index 88b9f2008487a..36412961ce75b 100644 --- a/packages/kbn-test/src/functional_test_runner/cli.ts +++ b/packages/kbn-test/src/functional_test_runner/cli.ts @@ -18,24 +18,36 @@ */ import { resolve } from 'path'; -import { run } from '../../../../src/dev/run'; +import { run, createFlagError, Flags } from '@kbn/dev-utils'; import { FunctionalTestRunner } from './functional_test_runner'; +const makeAbsolutePath = (v: string) => resolve(process.cwd(), v); +const toArray = (v: string | string[]) => ([] as string[]).concat(v || []); +const parseInstallDir = (flags: Flags) => { + const flag = flags['kibana-install-dir']; + + if (typeof flag !== 'string' && flag !== undefined) { + throw createFlagError('--kibana-install-dir must be a string or not defined'); + } + + return flag ? makeAbsolutePath(flag) : undefined; +}; + export function runFtrCli() { run( async ({ flags, log }) => { - const resolveConfigPath = (v: string) => resolve(process.cwd(), v); - const toArray = (v: string | string[]) => ([] as string[]).concat(v || []); - const functionalTestRunner = new FunctionalTestRunner( log, - resolveConfigPath(flags.config as string), + makeAbsolutePath(flags.config as string), { mochaOpts: { bail: flags.bail, grep: flags.grep || undefined, invert: flags.invert, }, + kbnTestServer: { + installDir: parseInstallDir(flags), + }, suiteTags: { include: toArray(flags['include-tag'] as string | string[]), exclude: toArray(flags['exclude-tag'] as string | string[]), @@ -84,7 +96,7 @@ export function runFtrCli() { }, { flags: { - string: ['config', 'grep', 'exclude', 'include-tag', 'exclude-tag'], + string: ['config', 'grep', 'exclude', 'include-tag', 'exclude-tag', 'kibana-install-dir'], boolean: ['bail', 'invert', 'test-stats', 'updateBaselines'], default: { config: 'test/functional/config.js', @@ -100,6 +112,7 @@ export function runFtrCli() { --exclude-tag=tag a tag to be excluded, pass multiple times for multiple tags --test-stats print the number of tests (included and excluded) to STDERR --updateBaselines replace baseline screenshots with whatever is generated from the test + --kibana-install-dir directory where the Kibana install being tested resides `, }, } diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index 4887ad2c6e1d7..d9cf282d8f4b6 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -187,6 +187,7 @@ export const schema = Joi.object() buildArgs: Joi.array(), sourceArgs: Joi.array(), serverArgs: Joi.array(), + installDir: Joi.string(), }) .default(), diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js index 969ccff93f3be..ea697b096ce99 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js @@ -23,12 +23,11 @@ import Mocha from 'mocha'; import { ToolingLogTextWriter } from '@kbn/dev-utils'; import moment from 'moment'; -import { setupJUnitReportGeneration } from '../../../../../../../src/dev'; +import { recordLog, snapshotLogsForRunnable, setupJUnitReportGeneration } from '../../../../mocha'; import * as colors from './colors'; import * as symbols from './symbols'; import { ms } from './ms'; import { writeEpilogue } from './write_epilogue'; -import { recordLog, snapshotLogsForRunnable } from '../../../../../../../src/dev/mocha/log_cache'; export function MochaReporterProvider({ getService }) { const log = getService('log'); @@ -122,7 +121,7 @@ export function MochaReporterProvider({ getService }) { onSuiteEnd = () => { if (log.indent(-2) === 0) { - log.write(); + log.write(''); } }; diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/write_epilogue.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/write_epilogue.js index 003827120e930..72a011ce510bc 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/write_epilogue.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/write_epilogue.js @@ -22,7 +22,7 @@ import { ms } from './ms'; export function writeEpilogue(log, stats) { // header - log.write(); + log.write(''); // passes log.write(`${colors.pass('%d passing')} (%s)`, stats.passes || 0, ms(stats.duration)); @@ -38,5 +38,5 @@ export function writeEpilogue(log, stats) { } // footer - log.write(); + log.write(''); } diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js index 6746914fe0318..a425251a29f36 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js @@ -57,8 +57,8 @@ export async function setupMocha(lifecycle, log, config, providers) { filterSuitesByTags({ log, mocha, - include: config.get('suiteTags.include'), - exclude: config.get('suiteTags.exclude'), + include: config.get('suiteTags.include').map(tag => tag.replace(/-\d+$/, '')), + exclude: config.get('suiteTags.exclude').map(tag => tag.replace(/-\d+$/, '')), }); return mocha; diff --git a/packages/kbn-test/src/functional_tests/lib/paths.js b/packages/kbn-test/src/functional_tests/lib/paths.js index 6584f78163851..97ba44f4d711e 100644 --- a/packages/kbn-test/src/functional_tests/lib/paths.js +++ b/packages/kbn-test/src/functional_tests/lib/paths.js @@ -32,4 +32,4 @@ export const KIBANA_FTR_SCRIPT = resolve(KIBANA_ROOT, 'scripts/functional_test_r export const PROJECT_ROOT = resolve(__dirname, '../../../../../../'); export const FUNCTIONAL_CONFIG_PATH = resolve(KIBANA_ROOT, 'test/functional/config'); export const API_CONFIG_PATH = resolve(KIBANA_ROOT, 'test/api_integration/config'); -export const OPTIMIZE_BUNDLE_DIR = resolve(KIBANA_ROOT, 'optimize/bundles'); +export const OPTIMIZE_BUNDLE_DIR = resolve(KIBANA_ROOT, 'data/optimize/bundles'); diff --git a/packages/kbn-test/src/functional_tests/lib/run_ftr.js b/packages/kbn-test/src/functional_tests/lib/run_ftr.js index a0edfcdb8c7b5..aeda84f9524ed 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_ftr.js +++ b/packages/kbn-test/src/functional_tests/lib/run_ftr.js @@ -20,7 +20,10 @@ import { FunctionalTestRunner, readConfigFile } from '../../functional_test_runner'; import { CliError } from './run_cli'; -async function createFtr({ configPath, options: { log, bail, grep, updateBaselines, suiteTags } }) { +async function createFtr({ + configPath, + options: { installDir, log, bail, grep, updateBaselines, suiteTags }, +}) { const config = await readConfigFile(log, configPath); return new FunctionalTestRunner(log, configPath, { @@ -28,6 +31,9 @@ async function createFtr({ configPath, options: { log, bail, grep, updateBaselin bail: !!bail, grep, }, + kbnTestServer: { + installDir, + }, updateBaselines, suiteTags: { include: [...suiteTags.include, ...config.get('suiteTags.include')], diff --git a/packages/kbn-test/src/functional_tests/tasks.js b/packages/kbn-test/src/functional_tests/tasks.js index 966b148f0ce6d..6ebc49679fbf3 100644 --- a/packages/kbn-test/src/functional_tests/tasks.js +++ b/packages/kbn-test/src/functional_tests/tasks.js @@ -21,6 +21,7 @@ import { relative } from 'path'; import * as Rx from 'rxjs'; import { startWith, switchMap, take } from 'rxjs/operators'; import { withProcRunner } from '@kbn/dev-utils'; +import dedent from 'dedent'; import { runElasticsearch, @@ -33,14 +34,20 @@ import { import { readConfigFile } from '../functional_test_runner/lib'; -const SUCCESS_MESSAGE = ` +const makeSuccessMessage = options => { + const installDirFlag = options.installDir ? ` --kibana-install-dir=${options.installDir}` : ''; -Elasticsearch and Kibana are ready for functional testing. Start the functional tests -in another terminal session by running this command from this directory: + return ( + '\n\n' + + dedent` + Elasticsearch and Kibana are ready for functional testing. Start the functional tests + in another terminal session by running this command from this directory: - node ${relative(process.cwd(), KIBANA_FTR_SCRIPT)} - -`; + node ${relative(process.cwd(), KIBANA_FTR_SCRIPT)}${installDirFlag} + ` + + '\n\n' + ); +}; /** * Run servers and tests for each config @@ -118,15 +125,15 @@ export async function startServers(options) { // wait for 5 seconds of silence before logging the // success message so that it doesn't get buried - await silence(5000, { log }); - log.info(SUCCESS_MESSAGE); + await silence(log, 5000); + log.success(makeSuccessMessage(options)); await procs.waitForAllToStop(); await es.cleanup(); }); } -async function silence(milliseconds, { log }) { +async function silence(log, milliseconds) { await log .getWritten$() .pipe( diff --git a/packages/kbn-test/src/index.js b/packages/kbn-test/src/index.js index e8cc694f5252e..8313d0c7334be 100644 --- a/packages/kbn-test/src/index.js +++ b/packages/kbn-test/src/index.js @@ -32,3 +32,10 @@ export { setupUsers, DEFAULT_SUPERUSER_PASS } from './functional_tests/lib/auth' export { readConfigFile } from './functional_test_runner/lib/config/read_config_file'; export { runFtrCli } from './functional_test_runner/cli'; + +export { + createAutoJUnitReporter, + runMochaCli, + setupJUnitReportGeneration, + escapeCdata, +} from './mocha'; diff --git a/src/dev/mocha/__tests__/fixtures/project/test.js b/packages/kbn-test/src/mocha/__tests__/fixtures/project/test.js similarity index 100% rename from src/dev/mocha/__tests__/fixtures/project/test.js rename to packages/kbn-test/src/mocha/__tests__/fixtures/project/test.js diff --git a/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js b/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js new file mode 100644 index 0000000000000..1b6dea9863bca --- /dev/null +++ b/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js @@ -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 { resolve } from 'path'; +import { readFileSync } from 'fs'; + +import { fromNode as fcb } from 'bluebird'; +import { parseString } from 'xml2js'; +import del from 'del'; +import Mocha from 'mocha'; +import expect from '@kbn/expect'; + +import { setupJUnitReportGeneration } from '../junit_report_generation'; + +const PROJECT_DIR = resolve(__dirname, 'fixtures/project'); +const DURATION_REGEX = /^\d+\.\d{3}$/; +const ISO_DATE_SEC_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/; + +describe('dev/mocha/junit report generation', () => { + afterEach(() => { + del.sync(resolve(PROJECT_DIR, 'target')); + }); + + it('reports on failed setup hooks', async () => { + const mocha = new Mocha({ + reporter: function Runner(runner) { + setupJUnitReportGeneration(runner, { + reportName: 'test', + rootDirectory: PROJECT_DIR, + }); + }, + }); + + mocha.addFile(resolve(PROJECT_DIR, 'test.js')); + await new Promise(resolve => mocha.run(resolve)); + const report = await fcb(cb => + parseString( + readFileSync(resolve(PROJECT_DIR, 'target/junit', process.env.JOB || '.', 'TEST-test.xml')), + cb + ) + ); + + // test case results are wrapped in + expect(report).to.eql({ + testsuites: { + testsuite: [report.testsuites.testsuite[0]], + }, + }); + + // the single element at the root contains summary data for all tests results + const [testsuite] = report.testsuites.testsuite; + expect(testsuite.$.time).to.match(DURATION_REGEX); + expect(testsuite.$.timestamp).to.match(ISO_DATE_SEC_REGEX); + expect(testsuite).to.eql({ + $: { + failures: '2', + skipped: '1', + tests: '4', + time: testsuite.$.time, + timestamp: testsuite.$.timestamp, + }, + testcase: testsuite.testcase, + }); + + // there are actually only three tests, but since the hook failed + // it is reported as a test failure + expect(testsuite.testcase).to.have.length(4); + const [testPass, testFail, beforeEachFail, testSkipped] = testsuite.testcase; + + const sharedClassname = testPass.$.classname; + expect(sharedClassname).to.match(/^test\.test[^\.]js$/); + expect(testPass.$.time).to.match(DURATION_REGEX); + expect(testPass).to.eql({ + $: { + classname: sharedClassname, + name: 'SUITE works', + time: testPass.$.time, + }, + 'system-out': testPass['system-out'], + }); + + expect(testFail.$.time).to.match(DURATION_REGEX); + expect(testFail.failure[0]).to.match(/Error: FORCE_TEST_FAIL\n.+fixtures.project.test.js/); + expect(testFail).to.eql({ + $: { + classname: sharedClassname, + name: 'SUITE fails', + time: testFail.$.time, + }, + 'system-out': testFail['system-out'], + failure: [testFail.failure[0]], + }); + + expect(beforeEachFail.$.time).to.match(DURATION_REGEX); + expect(beforeEachFail.failure).to.have.length(1); + expect(beforeEachFail.failure[0]).to.match( + /Error: FORCE_HOOK_FAIL\n.+fixtures.project.test.js/ + ); + expect(beforeEachFail).to.eql({ + $: { + classname: sharedClassname, + name: 'SUITE SUB_SUITE "before each" hook: fail hook for "never runs"', + time: beforeEachFail.$.time, + }, + 'system-out': testFail['system-out'], + failure: [beforeEachFail.failure[0]], + }); + + expect(testSkipped).to.eql({ + $: { + classname: sharedClassname, + name: 'SUITE SUB_SUITE never runs', + }, + 'system-out': testFail['system-out'], + skipped: [''], + }); + }); +}); diff --git a/src/dev/mocha/auto_junit_reporter.js b/packages/kbn-test/src/mocha/auto_junit_reporter.js similarity index 100% rename from src/dev/mocha/auto_junit_reporter.js rename to packages/kbn-test/src/mocha/auto_junit_reporter.js diff --git a/packages/kbn-test/src/mocha/index.js b/packages/kbn-test/src/mocha/index.js new file mode 100644 index 0000000000000..f18282d4a8b13 --- /dev/null +++ b/packages/kbn-test/src/mocha/index.js @@ -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 { createAutoJUnitReporter } from './auto_junit_reporter'; +export { setupJUnitReportGeneration } from './junit_report_generation'; +export { runMochaCli } from './run_mocha_cli'; +export { recordLog, snapshotLogsForRunnable } from './log_cache'; +export { escapeCdata } from './xml'; diff --git a/packages/kbn-test/src/mocha/junit_report_generation.js b/packages/kbn-test/src/mocha/junit_report_generation.js new file mode 100644 index 0000000000000..10701aaca1cc7 --- /dev/null +++ b/packages/kbn-test/src/mocha/junit_report_generation.js @@ -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 { resolve, dirname, relative } from 'path'; +import { writeFileSync } from 'fs'; +import { inspect } from 'util'; + +import mkdirp from 'mkdirp'; +import xmlBuilder from 'xmlbuilder'; + +import { getSnapshotOfRunnableLogs } from './log_cache'; +import { escapeCdata } from '../'; + +const dateNow = Date.now.bind(Date); + +export function setupJUnitReportGeneration(runner, options = {}) { + const { + reportName = 'Unnamed Mocha Tests', + rootDirectory = dirname(require.resolve('../../../../package.json')), + } = options; + + const stats = {}; + const results = []; + + const getDuration = node => + node.startTime && node.endTime ? ((node.endTime - node.startTime) / 1000).toFixed(3) : null; + + const findAllTests = suite => + suite.suites.reduce((acc, suite) => acc.concat(findAllTests(suite)), suite.tests); + + const setStartTime = node => { + node.startTime = dateNow(); + }; + + const setEndTime = node => { + node.endTime = dateNow(); + }; + + const getFullTitle = node => { + const parentTitle = node.parent && getFullTitle(node.parent); + return parentTitle ? `${parentTitle} ${node.title}` : node.title; + }; + + const getPath = node => { + if (node.file) { + return relative(rootDirectory, node.file); + } + + if (node.parent) { + return getPath(node.parent); + } + + return 'unknown'; + }; + + runner.on('start', () => setStartTime(stats)); + runner.on('suite', setStartTime); + runner.on('hook', setStartTime); + runner.on('hook end', setEndTime); + runner.on('test', setStartTime); + runner.on('pass', node => results.push({ node })); + runner.on('pass', setEndTime); + runner.on('fail', (node, error) => results.push({ failed: true, error, node })); + runner.on('fail', setEndTime); + runner.on('suite end', () => setEndTime(stats)); + + runner.on('end', () => { + // crawl the test graph to collect all defined tests + const allTests = findAllTests(runner.suite); + if (!allTests.length) { + return; + } + + // filter out just the failures + const failures = results.filter(result => result.failed); + + // any failure that isn't for a test is for a hook + const failedHooks = failures.filter(result => !allTests.includes(result.node)); + + // mocha doesn't emit 'pass' or 'fail' when it skips a test + // or a test is pending, so we find them ourselves + const skippedResults = allTests + .filter(node => node.pending || !results.find(result => result.node === node)) + .map(node => ({ skipped: true, node })); + + const builder = xmlBuilder.create( + 'testsuites', + { encoding: 'utf-8' }, + {}, + { skipNullAttributes: true } + ); + + const testsuitesEl = builder.ele('testsuite', { + timestamp: new Date(stats.startTime).toISOString().slice(0, -5), + time: getDuration(stats), + tests: allTests.length + failedHooks.length, + failures: failures.length, + skipped: skippedResults.length, + }); + + function addTestcaseEl(node) { + return testsuitesEl.ele('testcase', { + name: getFullTitle(node), + classname: `${reportName}.${getPath(node).replace(/\./g, '·')}`, + time: getDuration(node), + }); + } + + [...results, ...skippedResults].forEach(result => { + const el = addTestcaseEl(result.node); + el.ele('system-out').dat(escapeCdata(getSnapshotOfRunnableLogs(result.node) || '')); + + if (result.failed) { + el.ele('failure').dat(escapeCdata(inspect(result.error))); + return; + } + + if (result.skipped) { + el.ele('skipped'); + } + }); + + const reportPath = resolve( + rootDirectory, + 'target/junit', + process.env.JOB || '.', + `TEST-${reportName}.xml` + ); + + const reportXML = builder.end({ + pretty: true, + indent: ' ', + newline: '\n', + spacebeforeslash: '', + }); + + mkdirp.sync(dirname(reportPath)); + writeFileSync(reportPath, reportXML, 'utf8'); + }); +} diff --git a/src/dev/mocha/log_cache.js b/packages/kbn-test/src/mocha/log_cache.js similarity index 100% rename from src/dev/mocha/log_cache.js rename to packages/kbn-test/src/mocha/log_cache.js diff --git a/src/dev/mocha/run_mocha_cli.js b/packages/kbn-test/src/mocha/run_mocha_cli.js similarity index 77% rename from src/dev/mocha/run_mocha_cli.js rename to packages/kbn-test/src/mocha/run_mocha_cli.js index f914e2b2499eb..7a90108472721 100644 --- a/src/dev/mocha/run_mocha_cli.js +++ b/packages/kbn-test/src/mocha/run_mocha_cli.js @@ -17,8 +17,7 @@ * under the License. */ -import { resolve } from 'path'; - +import { REPO_ROOT } from '@kbn/dev-utils'; import getopts from 'getopts'; import globby from 'globby'; @@ -41,9 +40,6 @@ export function runMochaCli() { // prevent globals injected from canvas plugins from triggering leak check process.argv.push('--globals', '__core-js_shared__,core,_, '); - // ensure that mocha requires the setup_node_env script - process.argv.push('--require', require.resolve('../../setup_node_env')); - // set default test timeout if (opts.timeout == null && !opts['no-timeouts']) { if (runInBand) { @@ -67,19 +63,17 @@ export function runMochaCli() { if (!opts._.length) { globby .sync( - [ - 'src/**/__tests__/**/*.js', - 'packages/elastic-datemath/test/**/*.js', - 'packages/kbn-dev-utils/src/**/__tests__/**/*.js', - 'packages/kbn-es-query/src/**/__tests__/**/*.js', - 'packages/kbn-eslint-plugin-eslint/**/__tests__/**/*.js', - 'tasks/**/__tests__/**/*.js', - ], + ['src/**/__tests__/**/*.js', 'packages/**/__tests__/**/*.js', 'tasks/**/__tests__/**/*.js'], { - cwd: resolve(__dirname, '../../..'), + cwd: REPO_ROOT, onlyFiles: true, absolute: true, - ignore: ['**/__tests__/fixtures/**', 'src/**/public/**', '**/_*.js'], + ignore: [ + '**/__tests__/fixtures/**', + 'src/**/public/**', + '**/_*.js', + 'packages/**/target/**', + ], } ) .forEach(file => { diff --git a/src/dev/mocha/server_junit_reporter.js b/packages/kbn-test/src/mocha/server_junit_reporter.js similarity index 95% rename from src/dev/mocha/server_junit_reporter.js rename to packages/kbn-test/src/mocha/server_junit_reporter.js index e626f693e9af1..c629f401d0580 100644 --- a/src/dev/mocha/server_junit_reporter.js +++ b/packages/kbn-test/src/mocha/server_junit_reporter.js @@ -18,7 +18,7 @@ */ // when the reporter is loaded by mocha in child process it might be before setup_node_env -require('../../setup_node_env'); +require('../../../../src/setup_node_env'); module.exports = require('./auto_junit_reporter').createAutoJUnitReporter({ reportName: 'Server Mocha Tests', diff --git a/src/dev/xml.ts b/packages/kbn-test/src/mocha/xml.ts similarity index 100% rename from src/dev/xml.ts rename to packages/kbn-test/src/mocha/xml.ts diff --git a/packages/kbn-test/tsconfig.json b/packages/kbn-test/tsconfig.json index 83a0fe04a4b5f..825fddc0bdcc7 100644 --- a/packages/kbn-test/tsconfig.json +++ b/packages/kbn-test/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "include": [ "types/**/*", - "src/functional_test_runner/**/*" + "src/functional_test_runner/**/*", + "src/mocha/xml.ts" ] } diff --git a/packages/kbn-ui-framework/doc_site/src/index.js b/packages/kbn-ui-framework/doc_site/src/index.js index f53e8a608e1a1..d82df375c59f4 100644 --- a/packages/kbn-ui-framework/doc_site/src/index.js +++ b/packages/kbn-ui-framework/doc_site/src/index.js @@ -19,7 +19,8 @@ require('./main.scss'); -import '@babel/polyfill'; +import 'core-js/stable'; +import 'regenerator-runtime/runtime'; import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index f78066317a467..bd9658934100d 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -30,23 +30,23 @@ "enzyme-adapter-react-16": "^1.9.1" }, "devDependencies": { - "@babel/core": "7.4.5", - "@babel/polyfill": "7.4.4", + "@babel/core": "^7.5.5", "@elastic/eui": "0.0.55", "@kbn/babel-preset": "1.0.0", "autoprefixer": "9.6.1", - "babel-loader": "8.0.6", + "babel-loader": "^8.0.6", "brace": "0.11.1", - "chalk": "^2.4.1", - "chokidar": "3.0.1", - "css-loader": "^2.0.0", + "chalk": "^2.4.2", + "chokidar": "3.0.2", + "core-js": "^3.2.1", + "css-loader": "^2.1.1", "expose-loader": "^0.7.5", - "file-loader": "^4.0.0", + "file-loader": "^4.2.0", "grunt": "1.0.4", "grunt-babel": "^8.0.0", "grunt-contrib-clean": "^1.1.0", "grunt-contrib-copy": "^1.0.0", - "highlight.js": "9.15.8", + "highlight.js": "9.15.10", "html": "1.0.0", "html-loader": "^0.5.5", "imports-loader": "^0.8.0", @@ -56,7 +56,7 @@ "node-sass": "^4.9.4", "postcss": "^7.0.5", "postcss-loader": "^3.0.0", - "raw-loader": "^3.0.0", + "raw-loader": "^3.1.0", "react-dom": "^16.2.0", "react-redux": "^5.0.6", "react-router": "^3.2.0", @@ -64,11 +64,12 @@ "react-router-redux": "^4.0.8", "redux": "3.7.2", "redux-thunk": "2.2.0", - "sass-loader": "^7.1.0", - "sinon": "^7.2.2", + "regenerator-runtime": "^0.13.3", + "sass-loader": "^7.3.1", + "sinon": "^7.4.2", "style-loader": "^0.23.1", - "webpack": "^4.23.1", - "webpack-dev-server": "^3.1.10", + "webpack": "^4.39.2", + "webpack-dev-server": "^3.8.0", "yeoman-generator": "1.1.1", "yo": "2.0.6" } diff --git a/renovate.json5 b/renovate.json5 index 3e9c17c7fe0a7..7798909bd3f41 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -23,20 +23,20 @@ 'release_note:skip', 'renovate', 'v8.0.0', - 'v7.3.0', + 'v7.5.0', ], major: { labels: [ 'release_note:skip', 'renovate', 'v8.0.0', - 'v7.3.0', + 'v7.5.0', 'renovate:major', ], }, masterIssue: true, masterIssueApproval: true, - rangeStrategy: 'replace', + rangeStrategy: 'bump', npm: { lockFileMaintenance: { enabled: false, @@ -135,6 +135,7 @@ groupName: 'graphql related packages', packagePatterns: [ '(\\b|_)graphql(\\b|_)', + '(\\b|_)apollo(\\b|_)', ], }, { @@ -159,6 +160,7 @@ packagePatterns: [ '(\\b|_)vega(\\b|_)', ], + enabled: false, }, { groupSlug: 'language server', @@ -208,7 +210,7 @@ 'release_note:skip', 'renovate', 'v8.0.0', - 'v7.3.0', + 'v7.5.0', ':ml', ], }, @@ -232,6 +234,13 @@ ], allowedVersions: '^1.6.2', }, + { + groupSlug: 'storybook', + groupName: 'storybook related packages', + packagePatterns: [ + '(\\b|_)storybook(\\b|_)', + ], + }, { groupSlug: 'json-stable-stringify', groupName: 'json-stable-stringify related packages', @@ -360,6 +369,14 @@ '@types/has-ansi', ], }, + { + groupSlug: 'history', + groupName: 'history related packages', + packageNames: [ + 'history', + '@types/history', + ], + }, { groupSlug: 'humps', groupName: 'humps related packages', @@ -608,14 +625,6 @@ '@types/git-url-parse', ], }, - { - groupSlug: 'history', - groupName: 'history related packages', - packageNames: [ - 'history', - '@types/history', - ], - }, { groupSlug: 'jsdom', groupName: 'jsdom related packages', @@ -632,6 +641,14 @@ '@types/jsonwebtoken', ], }, + { + groupSlug: 'mapbox-gl', + groupName: 'mapbox-gl related packages', + packageNames: [ + 'mapbox-gl', + '@types/mapbox-gl', + ], + }, { groupSlug: 'memoize-one', groupName: 'memoize-one related packages', @@ -728,30 +745,6 @@ '@types/reduce-reducers', ], }, - { - groupSlug: '@storybook/addon-actions', - groupName: '@storybook/addon-actions related packages', - packageNames: [ - '@storybook/addon-actions', - '@types/storybook__addon-actions', - ], - }, - { - groupSlug: '@storybook/addon-info', - groupName: '@storybook/addon-info related packages', - packageNames: [ - '@storybook/addon-info', - '@types/storybook__addon-info', - ], - }, - { - groupSlug: '@storybook/addon-knobs', - groupName: '@storybook/addon-knobs related packages', - packageNames: [ - '@storybook/addon-knobs', - '@types/storybook__addon-knobs', - ], - }, { groupSlug: 'tar-fs', groupName: 'tar-fs related packages', @@ -880,7 +873,7 @@ }, ], }, - prConcurrentLimit: 6, + prConcurrentLimit: 0, vulnerabilityAlerts: { enabled: false, }, diff --git a/rfcs/text/0004_application_service_mounting.md b/rfcs/text/0004_application_service_mounting.md index 30e8d9a05b8b4..f6d06129dd4c2 100644 --- a/rfcs/text/0004_application_service_mounting.md +++ b/rfcs/text/0004_application_service_mounting.md @@ -18,14 +18,14 @@ import ReactDOM from 'react-dom'; import { MyApp } from './componnets'; -export function renderApp(context, targetDomElement) { +export function renderApp(context, { element }) { ReactDOM.render( , - targetDomElement + element ); return () => { - ReactDOM.unmountComponentAtNode(targetDomElement); + ReactDOM.unmountComponentAtNode(element); }; } ``` @@ -38,9 +38,9 @@ class MyPlugin { application.register({ id: 'my-app', title: 'My Application', - async mount(context, targetDomElement) { - const { renderApp } = await import('./applcation'); - return renderApp(context, targetDomElement); + async mount(context, params) { + const { renderApp } = await import('./application'); + return renderApp(context, params); } }); } @@ -63,9 +63,7 @@ lock-in. ```ts /** A context type that implements the Handler Context pattern from RFC-0003 */ -export interface MountContext { - /** This is the base path for setting up your router. */ - basename: string; +export interface AppMountContext { /** These services serve as an example, but are subject to change. */ core: { http: { @@ -93,6 +91,13 @@ export interface MountContext { [contextName: string]: unknown; } +export interface AppMountParams { + /** The base path the application is mounted on. Used to configure routers. */ + appBasePath: string; + /** The element the application should render into */ + element: HTMLElement; +} + export type Unmount = () => Promise | void; export interface AppSpec { @@ -109,11 +114,11 @@ export interface AppSpec { /** * A mount function called when the user navigates to this app's route. - * @param context the `MountContext generated for this app - * @param targetDomElement An HTMLElement to mount the application onto. + * @param context the `AppMountContext` generated for this app + * @param params the `AppMountParams` * @returns An unmounting function that will be called to unmount the application. */ - mount(context: MountContext, targetDomElement: HTMLElement): Unmount | Promise; + mount(context: MountContext, params: AppMountParams): Unmount | Promise; /** * A EUI iconType that will be used for the app's icon. This icon @@ -158,19 +163,21 @@ When an app is registered via `register`, it must provide a `mount` function that will be invoked whenever the window's location has changed from another app to this app. -This function is called with a `MountContext` and an `HTMLElement` for the -application to render itself to. The mount function must also return a function -that can be called by the ApplicationService to unmount the application at the -given DOM node. The mount function may return a Promise of an unmount function -in order to import UI code dynamically. +This function is called with a `AppMountContext` and an +`AppMountParams` which contains a `HTMLElement` for the application to +render itself to. The mount function must also return a function that can be +called by the ApplicationService to unmount the application at the given DOM +Element. The mount function may return a Promise of an unmount function in order +to import UI code dynamically. The ApplicationService's `register` method will only be available during the *setup* lifecycle event. This allows the system to know when all applications have been registered. -The `mount` function will also get access to the `MountContext` that has many of -the same core services available during the `start` lifecycle. Plugins can also -register additional context attributes via the `registerMountContext` function. +The `mount` function will also get access to the `AppMountContext` that +has many of the same core services available during the `start` lifecycle. +Plugins can also register additional context attributes via the +`registerMountContext` function. ## Routing @@ -190,7 +197,7 @@ An example: "overview" page: mykibana.com/app/my-app/overview When setting up a router, your application should only handle the part of the -URL following the `context.basename` provided when you application is mounted. +URL following the `params.appBasePath` provided when you application is mounted. ### Legacy Applications @@ -211,7 +218,7 @@ a full-featured router and code-splitting. Note that using React or any other 3rd party tools featured here is not required to build a Kibana Application. ```tsx -// my_plugin/public/application.ts +// my_plugin/public/application.tsx import React from 'react'; import ReactDOM from 'react-dom'; @@ -239,16 +246,16 @@ const MyApp = ({ basename }) => ( , ); -export function renderApp(context, targetDomElement) { +export function renderApp(context, params) { ReactDOM.render( - // `context.basename` would be `/app/my-app` in this example. - // This exact string is not guaranteed to be stable, always reference - // `context.basename`. - , - targetDomElem + // `params.appBasePath` would be `/app/my-app` in this example. + // This exact string is not guaranteed to be stable, always reference the + // provided value at `params.appBasePath`. + , + params.element ); - return () => ReactDOM.unmountComponentAtNode(targetDomElem); + return () => ReactDOM.unmountComponentAtNode(params.element); } ``` @@ -259,9 +266,9 @@ export class MyPlugin { setup({ application }) { application.register({ id: 'my-app', - async mount(context, targetDomElem) { - const { renderApp } = await import('./applcation'); - return renderApp(context, targetDomElement); + async mount(context, params) { + const { renderApp } = await import('./application'); + return renderApp(context, params); } }); } diff --git a/scripts/jest_integration.js b/scripts/jest_integration.js index 5eafcca2176cf..7da1436f5583c 100755 --- a/scripts/jest_integration.js +++ b/scripts/jest_integration.js @@ -31,6 +31,7 @@ var resolve = require('path').resolve; process.argv.push('--config', resolve(__dirname, '../src/dev/jest/config.integration.js')); +process.argv.push('--runInBand'); require('../src/setup_node_env'); require('../src/dev/jest/cli'); diff --git a/scripts/mocha.js b/scripts/mocha.js index e8d6c31d02ef2..8d25d18a594cc 100644 --- a/scripts/mocha.js +++ b/scripts/mocha.js @@ -18,4 +18,4 @@ */ require('../src/setup_node_env'); -require('../src/dev/mocha').runMochaCli(); +require('@kbn/test').runMochaCli(); diff --git a/src/cli/cluster/cluster_manager.js b/src/cli/cluster/cluster_manager.js index 342f838e4ee7a..bd32c5b9803a3 100644 --- a/src/cli/cluster/cluster_manager.js +++ b/src/cli/cluster/cluster_manager.js @@ -24,6 +24,7 @@ import opn from 'opn'; import { debounce, invoke, bindAll, once, uniq } from 'lodash'; import * as Rx from 'rxjs'; import { first, mapTo, filter, map, take } from 'rxjs/operators'; +import { REPO_ROOT } from '@kbn/dev-utils'; import Log from '../log'; import Worker from './worker'; @@ -102,8 +103,15 @@ export default class ClusterManager { if (opts.watch) { const pluginPaths = config.get('plugins.paths'); - const scanDirs = config.get('plugins.scanDirs'); - const extraPaths = [...pluginPaths, ...scanDirs]; + const scanDirs = [ + ...config.get('plugins.scanDirs'), + resolve(REPO_ROOT, 'src/plugins'), + resolve(REPO_ROOT, 'x-pack/plugins'), + ]; + const extraPaths = [ + ...pluginPaths, + ...scanDirs, + ]; const extraIgnores = scanDirs .map(scanDir => resolve(scanDir, '*')) diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index af4aef9f907ec..ee37ae48823b3 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -39,7 +39,7 @@ We'll start with an overview of how plugins work in the new platform, and we'll Plugins in the new platform are not especially novel or complicated to describe. Our intention wasn't to build some clever system that magically solved problems through abstractions and layers of obscurity, and we wanted to make sure plugins could continue to use most of the same technologies they use today, at least from a technical perspective. -New platform plugins exist in the `src/plugins` and `x-pack/legacy/plugins` directories. +New platform plugins exist in the `src/plugins` and `x-pack/plugins` directories. ### Architecture @@ -1072,6 +1072,7 @@ import { setup, start } from '../core_plugins/visualizations/public/legacy'; | `ui/vis` | `visualizations.types` | -- | | `ui/vis/vis_factory` | `visualizations.types` | -- | | `ui/vis/vis_filters` | `visualizations.filters` | -- | +| `ui/utils/parse_es_interval` | `import { parseEsInterval } from '../data/public'` | `parseEsInterval`, `ParsedInterval`, `InvalidEsCalendarIntervalError`, `InvalidEsIntervalFormatError` items were moved to the `Data Plugin` as a static code | #### Server-side @@ -1092,7 +1093,18 @@ _See also: [Server's CoreSetup API Docs](/docs/development/core/server/kibana-pl ### Configure plugin Kibana provides ConfigService if a plugin developer may want to support adjustable runtime behavior for their plugins. Access to Kibana config in New platform has been subject to significant refactoring. -In order to have access to a config, plugin *should*: + +Config service does not provide access to the whole config anymore. New platform plugin cannot read configuration parameters of the core services nor other plugins directly. Use plugin contract to provide data. + +```js +// your-plugin.js +// in Legacy platform +const basePath = config.get('server.basePath'); +// in New platform +const basePath = core.http.basePath.get(request); +``` + +In order to have access to your plugin config, you *should*: - Declare plugin specific "configPath" (will fallback to plugin "id" if not specified) in `kibana.json` file. - Export schema validation for config from plugin's main file. Schema is mandatory. If a plugin reads from the config without schema declaration, ConfigService will throw an error. ```typescript diff --git a/src/core/public/application/application_service.mock.ts b/src/core/public/application/application_service.mock.ts index 85d997f3dc9aa..a2db755224636 100644 --- a/src/core/public/application/application_service.mock.ts +++ b/src/core/public/application/application_service.mock.ts @@ -17,23 +17,51 @@ * under the License. */ +import { Subject } from 'rxjs'; + import { capabilitiesServiceMock } from './capabilities/capabilities_service.mock'; -import { ApplicationService, ApplicationSetup, ApplicationStart } from './application_service'; +import { ApplicationService } from './application_service'; +import { + ApplicationSetup, + InternalApplicationStart, + ApplicationStart, + InternalApplicationSetup, +} from './types'; type ApplicationServiceContract = PublicMethodsOf; const createSetupContractMock = (): jest.Mocked => ({ - registerApp: jest.fn(), + register: jest.fn(), + registerMountContext: jest.fn(), +}); + +const createInternalSetupContractMock = (): jest.Mocked => ({ + register: jest.fn(), registerLegacyApp: jest.fn(), + registerMountContext: jest.fn(), }); -const createStartContractMock = (): jest.Mocked => ({ - ...capabilitiesServiceMock.createStartContract(), +const createStartContractMock = (legacyMode = false): jest.Mocked => ({ + capabilities: capabilitiesServiceMock.createStartContract().capabilities, + navigateToApp: jest.fn(), + getUrlForApp: jest.fn(), + registerMountContext: jest.fn(), +}); + +const createInternalStartContractMock = (): jest.Mocked => ({ + availableApps: new Map(), + availableLegacyApps: new Map(), + capabilities: capabilitiesServiceMock.createStartContract().capabilities, + navigateToApp: jest.fn(), + getUrlForApp: jest.fn(), + registerMountContext: jest.fn(), + currentAppId$: new Subject(), + getComponent: jest.fn(), }); const createMock = (): jest.Mocked => ({ - setup: jest.fn().mockReturnValue(createSetupContractMock()), - start: jest.fn().mockReturnValue(createStartContractMock()), + setup: jest.fn().mockReturnValue(createInternalSetupContractMock()), + start: jest.fn().mockReturnValue(createInternalStartContractMock()), stop: jest.fn(), }); @@ -41,4 +69,7 @@ export const applicationServiceMock = { create: createMock, createSetupContract: createSetupContractMock, createStartContract: createStartContractMock, + + createInternalSetupContract: createInternalSetupContractMock, + createInternalStartContract: createInternalStartContractMock, }; diff --git a/src/core/public/application/application_service.test.mocks.ts b/src/core/public/application/application_service.test.mocks.ts index c28d0a203068a..d829cf18e56be 100644 --- a/src/core/public/application/application_service.test.mocks.ts +++ b/src/core/public/application/application_service.test.mocks.ts @@ -26,3 +26,11 @@ export const CapabilitiesServiceConstructor = jest jest.doMock('./capabilities', () => ({ CapabilitiesService: CapabilitiesServiceConstructor, })); + +export const MockHistory = { + push: jest.fn(), +}; +export const createBrowserHistoryMock = jest.fn().mockReturnValue(MockHistory); +jest.doMock('history', () => ({ + createBrowserHistory: createBrowserHistoryMock, +})); diff --git a/src/core/public/application/application_service.test.tsx b/src/core/public/application/application_service.test.tsx index d2266671367a2..5b374218a5932 100644 --- a/src/core/public/application/application_service.test.tsx +++ b/src/core/public/application/application_service.test.tsx @@ -17,57 +17,219 @@ * under the License. */ +import { shallow } from 'enzyme'; +import React from 'react'; + import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; -import { MockCapabilitiesService } from './application_service.test.mocks'; +import { MockCapabilitiesService, MockHistory } from './application_service.test.mocks'; import { ApplicationService } from './application_service'; +import { contextServiceMock } from '../context/context_service.mock'; +import { httpServiceMock } from '../http/http_service.mock'; + +describe('#setup()', () => { + describe('register', () => { + it('throws an error if two apps with the same id are registered', () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); + setup.register(Symbol(), { id: 'app1' } as any); + expect(() => + setup.register(Symbol(), { id: 'app1' } as any) + ).toThrowErrorMatchingInlineSnapshot( + `"An application is already registered with the id \\"app1\\""` + ); + }); + + it('throws error if additional apps are registered after setup', async () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); + const http = httpServiceMock.createStartContract(); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + await service.start({ http, injectedMetadata }); + expect(() => + setup.register(Symbol(), { id: 'app1' } as any) + ).toThrowErrorMatchingInlineSnapshot(`"Applications cannot be registered after \\"setup\\""`); + }); + }); + + describe('registerLegacyApp', () => { + it('throws an error if two apps with the same id are registered', () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); + setup.registerLegacyApp({ id: 'app2' } as any); + expect(() => + setup.registerLegacyApp({ id: 'app2' } as any) + ).toThrowErrorMatchingInlineSnapshot( + `"A legacy application is already registered with the id \\"app2\\""` + ); + }); + + it('throws error if additional apps are registered after setup', async () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); + const http = httpServiceMock.createStartContract(); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + await service.start({ http, injectedMetadata }); + expect(() => + setup.registerLegacyApp({ id: 'app2' } as any) + ).toThrowErrorMatchingInlineSnapshot(`"Applications cannot be registered after \\"setup\\""`); + }); + }); + + it("`registerMountContext` calls context container's registerContext", () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); + const container = context.createContextContainer.mock.results[0].value; + const pluginId = Symbol(); + const noop = () => {}; + setup.registerMountContext(pluginId, 'test' as any, noop as any); + expect(container.registerContext).toHaveBeenCalledWith(pluginId, 'test', noop); + }); +}); describe('#start()', () => { + beforeEach(() => { + MockHistory.push.mockReset(); + }); + it('exposes available apps from capabilities', async () => { const service = new ApplicationService(); - const setup = service.setup(); - setup.registerApp({ id: 'app1' } as any); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); + setup.register(Symbol(), { id: 'app1' } as any); setup.registerLegacyApp({ id: 'app2' } as any); + + const http = httpServiceMock.createStartContract(); const injectedMetadata = injectedMetadataServiceMock.createStartContract(); - const startContract = await service.start({ injectedMetadata }); + const startContract = await service.start({ http, injectedMetadata }); + expect(startContract.availableApps).toMatchInlineSnapshot(` -Array [ - Object { - "id": "app1", - }, -] -`); + Map { + "app1" => Object { + "id": "app1", + }, + } + `); expect(startContract.availableLegacyApps).toMatchInlineSnapshot(` -Array [ - Object { - "id": "app2", - }, -] -`); + Map { + "app2" => Object { + "id": "app2", + }, + } + `); }); it('passes registered applications to capabilities', async () => { const service = new ApplicationService(); - const setup = service.setup(); - setup.registerApp({ id: 'app1' } as any); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); + setup.register(Symbol(), { id: 'app1' } as any); + + const http = httpServiceMock.createStartContract(); const injectedMetadata = injectedMetadataServiceMock.createStartContract(); - await service.start({ injectedMetadata }); + await service.start({ http, injectedMetadata }); + expect(MockCapabilitiesService.start).toHaveBeenCalledWith({ - apps: [{ id: 'app1' }], - legacyApps: [], + apps: new Map([['app1', { id: 'app1' }]]), + legacyApps: new Map(), injectedMetadata, }); }); it('passes registered legacy applications to capabilities', async () => { const service = new ApplicationService(); - const setup = service.setup(); + const context = contextServiceMock.createSetupContract(); + const setup = service.setup({ context }); setup.registerLegacyApp({ id: 'legacyApp1' } as any); + + const http = httpServiceMock.createStartContract(); const injectedMetadata = injectedMetadataServiceMock.createStartContract(); - await service.start({ injectedMetadata }); + await service.start({ http, injectedMetadata }); + expect(MockCapabilitiesService.start).toHaveBeenCalledWith({ - apps: [], - legacyApps: [{ id: 'legacyApp1' }], + apps: new Map(), + legacyApps: new Map([['legacyApp1', { id: 'legacyApp1' }]]), injectedMetadata, }); }); + + it('returns renderable JSX tree', async () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + service.setup({ context }); + + const http = httpServiceMock.createStartContract(); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + injectedMetadata.getLegacyMode.mockReturnValue(false); + const start = await service.start({ http, injectedMetadata }); + + expect(() => shallow(React.createElement(() => start.getComponent()))).not.toThrow(); + }); + + describe('navigateToApp', () => { + it('changes the browser history to /app/:appId', async () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + service.setup({ context }); + + const http = httpServiceMock.createStartContract(); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + injectedMetadata.getLegacyMode.mockReturnValue(false); + const start = await service.start({ http, injectedMetadata }); + + start.navigateToApp('myTestApp'); + expect(MockHistory.push).toHaveBeenCalledWith('/app/myTestApp', undefined); + start.navigateToApp('myOtherApp'); + expect(MockHistory.push).toHaveBeenCalledWith('/app/myOtherApp', undefined); + }); + + it('appends a path if specified', async () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + service.setup({ context }); + + const http = httpServiceMock.createStartContract(); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + injectedMetadata.getLegacyMode.mockReturnValue(false); + const start = await service.start({ http, injectedMetadata }); + + start.navigateToApp('myTestApp', { path: 'deep/link/to/location/2' }); + expect(MockHistory.push).toHaveBeenCalledWith( + '/app/myTestApp/deep/link/to/location/2', + undefined + ); + }); + + it('includes state if specified', async () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + service.setup({ context }); + + const http = httpServiceMock.createStartContract(); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + injectedMetadata.getLegacyMode.mockReturnValue(false); + const start = await service.start({ http, injectedMetadata }); + + start.navigateToApp('myTestApp', { state: 'my-state' }); + expect(MockHistory.push).toHaveBeenCalledWith('/app/myTestApp', 'my-state'); + }); + + it('redirects when in legacyMode', async () => { + const service = new ApplicationService(); + const context = contextServiceMock.createSetupContract(); + service.setup({ context }); + + const http = httpServiceMock.createStartContract(); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + injectedMetadata.getLegacyMode.mockReturnValue(true); + const redirectTo = jest.fn(); + const start = await service.start({ http, injectedMetadata, redirectTo }); + start.navigateToApp('myTestApp'); + expect(redirectTo).toHaveBeenCalledWith('/app/myTestApp'); + }); + }); }); diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index 528b81ad40be7..d1855a0370f00 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -17,108 +17,43 @@ * under the License. */ -import { Observable, BehaviorSubject } from 'rxjs'; -import { CapabilitiesService, Capabilities } from './capabilities'; -import { InjectedMetadataStart } from '../injected_metadata'; -import { RecursiveReadonly } from '../../utils'; - -interface BaseApp { - id: string; - - /** - * An ordinal used to sort nav links relative to one another for display. - */ - order: number; - - /** - * The title of the application. - */ - title: string; - - /** - * An observable for a tooltip shown when hovering over app link. - */ - tooltip$?: Observable; - - /** - * A EUI iconType that will be used for the app's icon. This icon - * takes precendence over the `icon` property. - */ - euiIconType?: string; - - /** - * A URL to an image file used as an icon. Used as a fallback - * if `euiIconType` is not provided. - */ - icon?: string; - - /** - * Custom capabilities defined by the app. - */ - capabilities?: Partial; -} - -/** @public */ -export interface App extends BaseApp { - /** - * A mount function called when the user navigates to this app's `rootRoute`. - * @param targetDomElement An HTMLElement to mount the application onto. - * @returns An unmounting function that will be called to unmount the application. - */ - mount(targetDomElement: HTMLElement): () => void; -} - -/** @internal */ -export interface LegacyApp extends BaseApp { - appUrl: string; - subUrlBase?: string; - linkToLastSubUrl?: boolean; -} - -/** @internal */ -export type MixedApp = Partial & Partial & BaseApp; - -/** @public */ -export interface ApplicationSetup { - /** - * Register an mountable application to the system. Apps will be mounted based on their `rootRoute`. - * @param app - */ - registerApp(app: App): void; +import { createBrowserHistory } from 'history'; +import { BehaviorSubject } from 'rxjs'; +import React from 'react'; - /** - * Register metadata about legacy applications. Legacy apps will not be mounted when navigated to. - * @param app - * @internal - */ - registerLegacyApp(app: LegacyApp): void; +import { InjectedMetadataStart } from '../injected_metadata'; +import { CapabilitiesService } from './capabilities'; +import { AppRouter } from './ui'; +import { HttpStart } from '../http'; +import { ContextSetup, IContextContainer } from '../context'; +import { + AppMountContext, + App, + LegacyApp, + AppMounter, + AppUnmount, + AppMountParameters, + InternalApplicationSetup, + InternalApplicationStart, +} from './types'; + +interface SetupDeps { + context: ContextSetup; } -/** - * @public - */ -export interface ApplicationStart { - /** - * Gets the read-only capabilities. - */ - capabilities: RecursiveReadonly; - - /** - * Apps available based on the current capabilities. Should be used - * to show navigation links and make routing decisions. - */ - availableApps: readonly App[]; - +interface StartDeps { + http: HttpStart; + injectedMetadata: InjectedMetadataStart; /** - * Apps available based on the current capabilities. Should be used - * to show navigation links and make routing decisions. - * @internal + * Only necessary for redirecting to legacy apps + * @deprecated */ - availableLegacyApps: readonly LegacyApp[]; + redirectTo?: (path: string) => void; } -interface StartDeps { - injectedMetadata: InjectedMetadataStart; +interface AppBox { + app: App; + mount: AppMounter; } /** @@ -126,31 +61,122 @@ interface StartDeps { * @internal */ export class ApplicationService { - private readonly apps$ = new BehaviorSubject([]); - private readonly legacyApps$ = new BehaviorSubject([]); + private readonly apps$ = new BehaviorSubject>(new Map()); + private readonly legacyApps$ = new BehaviorSubject>(new Map()); private readonly capabilities = new CapabilitiesService(); + private mountContext?: IContextContainer< + AppMountContext, + AppUnmount | Promise, + [AppMountParameters] + >; + + public setup({ context }: SetupDeps): InternalApplicationSetup { + this.mountContext = context.createContextContainer(); - public setup(): ApplicationSetup { return { - registerApp: (app: App) => { - this.apps$.next([...this.apps$.value, app]); + register: (plugin: symbol, app: App) => { + if (this.apps$.value.has(app.id)) { + throw new Error(`An application is already registered with the id "${app.id}"`); + } + if (this.apps$.isStopped) { + throw new Error(`Applications cannot be registered after "setup"`); + } + + const appBox: AppBox = { + app, + mount: this.mountContext!.createHandler(plugin, app.mount), + }; + this.apps$.next(new Map([...this.apps$.value.entries(), [app.id, appBox]])); }, registerLegacyApp: (app: LegacyApp) => { - this.legacyApps$.next([...this.legacyApps$.value, app]); + if (this.legacyApps$.value.has(app.id)) { + throw new Error(`A legacy application is already registered with the id "${app.id}"`); + } + if (this.legacyApps$.isStopped) { + throw new Error(`Applications cannot be registered after "setup"`); + } + + this.legacyApps$.next(new Map([...this.legacyApps$.value.entries(), [app.id, app]])); }, + registerMountContext: this.mountContext.registerContext, }; } - public async start({ injectedMetadata }: StartDeps): Promise { + public async start({ + http, + injectedMetadata, + redirectTo = (path: string) => (window.location.href = path), + }: StartDeps): Promise { + if (!this.mountContext) { + throw new Error(`ApplicationService#setup() must be invoked before start.`); + } + + // Disable registration of new applications this.apps$.complete(); this.legacyApps$.complete(); - return this.capabilities.start({ - apps: this.apps$.value, + const legacyMode = injectedMetadata.getLegacyMode(); + const currentAppId$ = new BehaviorSubject(undefined); + const { availableApps, availableLegacyApps, capabilities } = await this.capabilities.start({ + apps: new Map([...this.apps$.value].map(([id, { app }]) => [id, app])), legacyApps: this.legacyApps$.value, injectedMetadata, }); + + // Only setup history if we're not in legacy mode + const history = legacyMode ? null : createBrowserHistory({ basename: http.basePath.get() }); + + return { + availableApps, + availableLegacyApps, + capabilities, + registerMountContext: this.mountContext.registerContext, + currentAppId$, + + getUrlForApp: (appId, options: { path?: string } = {}) => { + return http.basePath.prepend(appPath(appId, options)); + }, + + navigateToApp: (appId, { path, state }: { path?: string; state?: any } = {}) => { + if (legacyMode) { + // If we're in legacy mode, do a full page refresh to load the NP app. + redirectTo(http.basePath.prepend(appPath(appId, { path }))); + } else { + // basePath not needed here because `history` is configured with basename + history!.push(appPath(appId, { path }), state); + } + }, + + getComponent: () => { + if (legacyMode) { + return null; + } + + // Filter only available apps and map to just the mount function. + const appMounters = new Map( + [...this.apps$.value] + .filter(([id]) => availableApps.has(id)) + .map(([id, { mount }]) => [id, mount]) + ); + + return ( + + ); + }, + }; } public stop() {} } + +const appPath = (appId: string, { path }: { path?: string } = {}): string => + path + ? `/app/${appId}/${path.replace(/^\//, '')}` // Remove preceding slash from path if present + : `/app/${appId}`; diff --git a/src/core/public/application/capabilities/capabilities_service.mock.ts b/src/core/public/application/capabilities/capabilities_service.mock.ts index 71b069fd80434..29c3275f0e3b2 100644 --- a/src/core/public/application/capabilities/capabilities_service.mock.ts +++ b/src/core/public/application/capabilities/capabilities_service.mock.ts @@ -18,11 +18,11 @@ */ import { CapabilitiesService, CapabilitiesStart } from './capabilities_service'; import { deepFreeze } from '../../../utils/'; -import { App, LegacyApp } from '../application_service'; +import { App, LegacyApp } from '../types'; const createStartContractMock = ( - apps: readonly App[] = [], - legacyApps: readonly LegacyApp[] = [] + apps: ReadonlyMap = new Map(), + legacyApps: ReadonlyMap = new Map() ): jest.Mocked => ({ availableApps: apps, availableLegacyApps: legacyApps, diff --git a/src/core/public/application/capabilities/capabilities_service.test.ts b/src/core/public/application/capabilities/capabilities_service.test.ts index 1c60c1eeb195a..e80e9a7af321a 100644 --- a/src/core/public/application/capabilities/capabilities_service.test.ts +++ b/src/core/public/application/capabilities/capabilities_service.test.ts @@ -19,6 +19,7 @@ import { InjectedMetadataService } from '../../injected_metadata'; import { CapabilitiesService } from './capabilities_service'; +import { LegacyApp, App } from '../types'; describe('#start', () => { const injectedMetadata = new InjectedMetadataService({ @@ -39,17 +40,22 @@ describe('#start', () => { } as any, }).start(); - const apps = [{ id: 'app1' }, { id: 'app2', capabilities: { app2: { feature: true } } }] as any; - const legacyApps = [ - { id: 'legacyApp1' }, - { id: 'legacyApp2', capabilities: { app2: { feature: true } } }, - ] as any; + const apps = new Map([ + ['app1', { id: 'app1' }], + ['app2', { id: 'app2', capabilities: { app2: { feature: true } } }], + ] as Array<[string, App]>); + const legacyApps = new Map([ + ['legacyApp1', { id: 'legacyApp1' }], + ['legacyApp2', { id: 'legacyApp2', capabilities: { app2: { feature: true } } }], + ] as Array<[string, LegacyApp]>); it('filters available apps based on returned navLinks', async () => { const service = new CapabilitiesService(); const startContract = await service.start({ apps, legacyApps, injectedMetadata }); - expect(startContract.availableApps).toEqual([{ id: 'app1' }]); - expect(startContract.availableLegacyApps).toEqual([{ id: 'legacyApp1' }]); + expect(startContract.availableApps).toEqual(new Map([['app1', { id: 'app1' }]])); + expect(startContract.availableLegacyApps).toEqual( + new Map([['legacyApp1', { id: 'legacyApp1' }]]) + ); }); it('does not allow Capabilities to be modified', async () => { diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index 51c5a218e70bd..b080f8c138cf2 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -18,12 +18,12 @@ */ import { deepFreeze, RecursiveReadonly } from '../../../utils'; -import { LegacyApp, App } from '../application_service'; +import { LegacyApp, App } from '../types'; import { InjectedMetadataStart } from '../../injected_metadata'; interface StartDeps { - apps: readonly App[]; - legacyApps: readonly LegacyApp[]; + apps: ReadonlyMap; + legacyApps: ReadonlyMap; injectedMetadata: InjectedMetadataStart; } @@ -53,8 +53,8 @@ export interface Capabilities { /** @internal */ export interface CapabilitiesStart { capabilities: RecursiveReadonly; - availableApps: readonly App[]; - availableLegacyApps: readonly LegacyApp[]; + availableApps: ReadonlyMap; + availableLegacyApps: ReadonlyMap; } /** @@ -68,10 +68,23 @@ export class CapabilitiesService { injectedMetadata, }: StartDeps): Promise { const capabilities = deepFreeze(injectedMetadata.getCapabilities()); + const availableApps = new Map( + [...apps].filter( + ([appId]) => + capabilities.navLinks[appId] === undefined || capabilities.navLinks[appId] === true + ) + ); + + const availableLegacyApps = new Map( + [...legacyApps].filter( + ([appId]) => + capabilities.navLinks[appId] === undefined || capabilities.navLinks[appId] === true + ) + ); return { - availableApps: apps.filter(app => capabilities.navLinks[app.id]), - availableLegacyApps: legacyApps.filter(app => capabilities.navLinks[app.id]), + availableApps, + availableLegacyApps, capabilities, }; } diff --git a/src/core/public/application/index.ts b/src/core/public/application/index.ts index 137b46e6573e6..ae25b54cf07a8 100644 --- a/src/core/public/application/index.ts +++ b/src/core/public/application/index.ts @@ -17,5 +17,17 @@ * under the License. */ -export { ApplicationService, ApplicationSetup, ApplicationStart } from './application_service'; +export { ApplicationService } from './application_service'; export { Capabilities } from './capabilities'; +export { + App, + AppBase, + AppUnmount, + AppMountContext, + AppMountParameters, + ApplicationSetup, + ApplicationStart, + // Internal types + InternalApplicationStart, + LegacyApp, +} from './types'; diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx new file mode 100644 index 0000000000000..e6a1070e1a684 --- /dev/null +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -0,0 +1,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. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { mount, ReactWrapper } from 'enzyme'; +import { createMemoryHistory, History } from 'history'; +import { BehaviorSubject } from 'rxjs'; + +import { I18nProvider } from '@kbn/i18n/react'; + +import { AppMounter, LegacyApp, AppMountParameters } from '../types'; +import { httpServiceMock } from '../../http/http_service.mock'; +import { AppRouter, AppNotFound } from '../ui'; + +const createMountHandler = (htmlString: string) => + jest.fn(async ({ appBasePath: basename, element: el }: AppMountParameters) => { + ReactDOM.render( +

, + el + ); + return jest.fn(() => ReactDOM.unmountComponentAtNode(el)); + }); + +describe('AppContainer', () => { + let apps: Map, Parameters>>; + let legacyApps: Map; + let history: History; + let router: ReactWrapper; + let redirectTo: jest.Mock; + let currentAppId$: BehaviorSubject; + + const navigate = async (path: string) => { + history.push(path); + router.update(); + // flushes any pending promises + return new Promise(resolve => setImmediate(resolve)); + }; + + beforeEach(() => { + redirectTo = jest.fn(); + apps = new Map([ + ['app1', createMountHandler('App 1')], + ['app2', createMountHandler('
App 2
')], + ]); + legacyApps = new Map([ + ['legacyApp1', { id: 'legacyApp1' }], + ['baseApp:legacyApp2', { id: 'baseApp:legacyApp2' }], + ]) as Map; + history = createMemoryHistory(); + currentAppId$ = new BehaviorSubject(undefined); + // Use 'asdf' as the basepath + const http = httpServiceMock.createStartContract({ basePath: '/asdf' }); + router = mount( + + + + ); + }); + + it('calls mountHandler and returned unmount function when navigating between apps', async () => { + await navigate('/app/app1'); + expect(apps.get('app1')!).toHaveBeenCalled(); + expect(router.html()).toMatchInlineSnapshot(` + "
+ basename: /asdf/app/app1 + html: App 1 +
" + `); + + const app1Unmount = await apps.get('app1')!.mock.results[0].value; + await navigate('/app/app2'); + expect(app1Unmount).toHaveBeenCalled(); + + expect(apps.get('app2')!).toHaveBeenCalled(); + expect(router.html()).toMatchInlineSnapshot(` + "
+ basename: /asdf/app/app2 + html:
App 2
+
" + `); + }); + + it('updates currentApp$ after mounting', async () => { + await navigate('/app/app1'); + expect(currentAppId$.value).toEqual('app1'); + await navigate('/app/app2'); + expect(currentAppId$.value).toEqual('app2'); + }); + + it('sets window.location.href when navigating to legacy apps', async () => { + await navigate('/app/legacyApp1'); + expect(redirectTo).toHaveBeenCalledWith('/asdf/app/legacyApp1'); + }); + + it('handles legacy apps with subapps', async () => { + await navigate('/app/baseApp'); + expect(redirectTo).toHaveBeenCalledWith('/asdf/app/baseApp'); + }); + + it('displays error page if no app is found', async () => { + await navigate('/app/unknown'); + expect(router.exists(AppNotFound)).toBe(true); + }); +}); diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts new file mode 100644 index 0000000000000..018d7569ce411 --- /dev/null +++ b/src/core/public/application/types.ts @@ -0,0 +1,300 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, Subject } from 'rxjs'; + +import { Capabilities } from './capabilities'; +import { ChromeStart } from '../chrome'; +import { IContextProvider } from '../context'; +import { DocLinksStart } from '../doc_links'; +import { HttpStart } from '../http'; +import { I18nStart } from '../i18n'; +import { NotificationsStart } from '../notifications'; +import { OverlayStart } from '../overlays'; +import { PluginOpaqueId } from '../plugins'; +import { UiSettingsClientContract } from '../ui_settings'; +import { RecursiveReadonly } from '../../utils'; + +/** @public */ +export interface AppBase { + id: string; + + /** + * The title of the application. + */ + title: string; + + /** + * An ordinal used to sort nav links relative to one another for display. + */ + order?: number; + + /** + * An observable for a tooltip shown when hovering over app link. + */ + tooltip$?: Observable; + + /** + * A EUI iconType that will be used for the app's icon. This icon + * takes precendence over the `icon` property. + */ + euiIconType?: string; + + /** + * A URL to an image file used as an icon. Used as a fallback + * if `euiIconType` is not provided. + */ + icon?: string; + + /** + * Custom capabilities defined by the app. + */ + capabilities?: Partial; +} + +/** + * Extension of {@link AppBase | common app properties} with the mount function. + * @public + */ +export interface App extends AppBase { + /** + * A mount function called when the user navigates to this app's route. + * @param context The mount context for this app. + * @param targetDomElement An HTMLElement to mount the application onto. + * @returns An unmounting function that will be called to unmount the application. + */ + mount: (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; +} + +/** @internal */ +export interface LegacyApp extends AppBase { + appUrl: string; + subUrlBase?: string; + linkToLastSubUrl?: boolean; +} + +/** + * The context object received when applications are mounted to the DOM. + * @public + */ +export interface AppMountContext { + /** + * Core service APIs available to mounted applications. + */ + core: { + /** {@link ApplicationStart} */ + application: Pick; + /** {@link ChromeStart} */ + chrome: ChromeStart; + /** {@link DocLinksStart} */ + docLinks: DocLinksStart; + /** {@link HttpStart} */ + http: HttpStart; + /** {@link I18nStart} */ + i18n: I18nStart; + /** {@link NotificationsStart} */ + notifications: NotificationsStart; + /** {@link OverlayStart} */ + overlays: OverlayStart; + /** {@link UiSettingsClient} */ + uiSettings: UiSettingsClientContract; + }; +} + +/** @public */ +export interface AppMountParameters { + /** + * The container element to render the application into. + */ + element: HTMLElement; + + /** + * The base path for configuring the application's router. + * + * @example + * + * How to configure react-router with a base path: + * + * ```ts + * // inside your plugin's setup function + * export class MyPlugin implements Plugin { + * setup({ application }) { + * application.register({ + * id: 'my-app', + * async mount(context, params) { + * const { renderApp } = await import('./application'); + * return renderApp(context, params); + * }, + * }); + * } + * ``` + * + * ```ts + * // application.tsx + * import React from 'react'; + * import ReactDOM from 'react-dom'; + * import { BrowserRouter, Route } from 'react-router-dom'; + * + * export renderApp = (context, { appBasePath, element }) => { + * ReactDOM.render( + * // pass `appBasePath` to `basename` + * + * + * , + * element + * ); + * + * return () => ReactDOM.unmountComponentAtNode(element); + * } + * ``` + */ + appBasePath: string; +} + +/** + * A function called when an application should be unmounted from the page. This function should be synchronous. + * @public + */ +export type AppUnmount = () => void; + +/** @internal */ +export type AppMounter = (params: AppMountParameters) => Promise; + +/** @public */ +export interface ApplicationSetup { + /** + * Register an mountable application to the system. + * @param app - an {@link App} + */ + register(app: App): void; + + /** + * Register a context provider for application mounting. Will only be available to applications that depend on the + * plugin that registered this context. + * + * @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to. + * @param provider - A {@link IContextProvider} function + */ + registerMountContext( + contextName: T, + provider: IContextProvider + ): void; +} + +/** @internal */ +export interface InternalApplicationSetup { + /** + * Register an mountable application to the system. + * @param plugin - opaque ID of the plugin that registers this application + * @param app + */ + register(plugin: PluginOpaqueId, app: App): void; + + /** + * Register metadata about legacy applications. Legacy apps will not be mounted when navigated to. + * @param app + * @internal + */ + registerLegacyApp(app: LegacyApp): void; + + /** + * Register a context provider for application mounting. Will only be available to applications that depend on the + * plugin that registered this context. + * + * @param pluginOpaqueId - The opaque ID of the plugin that is registering the context. + * @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to. + * @param provider - A {@link IContextProvider} function + */ + registerMountContext( + pluginOpaqueId: PluginOpaqueId, + contextName: T, + provider: IContextProvider + ): void; +} + +/** @public */ +export interface ApplicationStart { + /** + * Gets the read-only capabilities. + */ + capabilities: RecursiveReadonly; + + /** + * Navigiate to a given app + * + * @param appId + * @param options.path - optional path inside application to deep link to + * @param options.state - optional state to forward to the application + */ + navigateToApp(appId: string, options?: { path?: string; state?: any }): void; + + /** + * Returns a relative URL to a given app, including the global base path. + * @param appId + * @param options.path - optional path inside application to deep link to + */ + getUrlForApp(appId: string, options?: { path?: string }): string; + + /** + * Register a context provider for application mounting. Will only be available to applications that depend on the + * plugin that registered this context. + * + * @param pluginOpaqueId - The opaque ID of the plugin that is registering the context. + * @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to. + * @param provider - A {@link IContextProvider} function + */ + registerMountContext( + contextName: T, + provider: IContextProvider + ): void; +} + +/** @internal */ +export interface InternalApplicationStart + extends Pick { + /** + * Apps available based on the current capabilities. Should be used + * to show navigation links and make routing decisions. + */ + availableApps: ReadonlyMap; + /** + * Apps available based on the current capabilities. Should be used + * to show navigation links and make routing decisions. + * @internal + */ + availableLegacyApps: ReadonlyMap; + + /** + * Register a context provider for application mounting. Will only be available to applications that depend on the + * plugin that registered this context. + * + * @param pluginOpaqueId - The opaque ID of the plugin that is registering the context. + * @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to. + * @param provider - A {@link IContextProvider} function + */ + registerMountContext( + pluginOpaqueId: PluginOpaqueId, + contextName: T, + provider: IContextProvider + ): void; + + // Internal APIs + currentAppId$: Subject; + getComponent(): JSX.Element | null; +} diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx new file mode 100644 index 0000000000000..876cd3aa3a3d3 --- /dev/null +++ b/src/core/public/application/ui/app_container.tsx @@ -0,0 +1,111 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { RouteComponentProps } from 'react-router-dom'; +import { Subject } from 'rxjs'; + +import { LegacyApp, AppMounter, AppUnmount } from '../types'; +import { HttpStart } from '../../http'; +import { AppNotFound } from './app_not_found_screen'; + +interface Props extends RouteComponentProps<{ appId: string }> { + apps: ReadonlyMap; + legacyApps: ReadonlyMap; + basePath: HttpStart['basePath']; + currentAppId$: Subject; + /** + * Only necessary for redirecting to legacy apps + * @deprecated + */ + redirectTo: (path: string) => void; +} + +interface State { + appNotFound: boolean; +} + +export class AppContainer extends React.Component { + private readonly containerDiv = React.createRef(); + private unmountFunc?: AppUnmount; + + state: State = { appNotFound: false }; + + componentDidMount() { + this.mountApp(); + } + + componentWillUnmount() { + this.unmountApp(); + } + + componentDidUpdate(prevProps: Props) { + if (prevProps.match.params.appId !== this.props.match.params.appId) { + this.unmountApp(); + this.mountApp(); + } + } + + async mountApp() { + const { apps, legacyApps, match, basePath, currentAppId$, redirectTo } = this.props; + const { appId } = match.params; + + const mount = apps.get(appId); + if (mount) { + this.unmountFunc = await mount({ + appBasePath: basePath.prepend(`/app/${appId}`), + element: this.containerDiv.current!, + }); + currentAppId$.next(appId); + this.setState({ appNotFound: false }); + return; + } + + const legacyApp = findLegacyApp(appId, legacyApps); + if (legacyApp) { + this.unmountApp(); + redirectTo(basePath.prepend(`/app/${appId}`)); + this.setState({ appNotFound: false }); + return; + } + + this.setState({ appNotFound: true }); + } + + async unmountApp() { + if (this.unmountFunc) { + this.unmountFunc(); + this.unmountFunc = undefined; + } + } + + render() { + return ( + + {this.state.appNotFound && } +
+ + ); + } +} + +function findLegacyApp(appId: string, apps: ReadonlyMap) { + const matchingApps = [...apps.entries()].filter(([id]) => id.split(':')[0] === appId); + return matchingApps.length ? matchingApps[0][1] : null; +} diff --git a/src/core/public/application/ui/app_not_found_screen.tsx b/src/core/public/application/ui/app_not_found_screen.tsx new file mode 100644 index 0000000000000..73a999c5dbf16 --- /dev/null +++ b/src/core/public/application/ui/app_not_found_screen.tsx @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { EuiEmptyPrompt, EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +export const AppNotFound = () => ( + + + + + + + } + body={ +

+ +

+ } + /> +
+
+
+); diff --git a/src/core/public/application/ui/app_router.tsx b/src/core/public/application/ui/app_router.tsx new file mode 100644 index 0000000000000..9d8acf1978556 --- /dev/null +++ b/src/core/public/application/ui/app_router.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 { History } from 'history'; +import React from 'react'; +import { Router, Route } from 'react-router-dom'; +import { Subject } from 'rxjs'; + +import { LegacyApp, AppMounter } from '../types'; +import { AppContainer } from './app_container'; +import { HttpStart } from '../../http'; + +interface Props { + apps: ReadonlyMap; + legacyApps: ReadonlyMap; + basePath: HttpStart['basePath']; + currentAppId$: Subject; + history: History; + /** + * Only necessary for redirecting to legacy apps + * @deprecated + */ + redirectTo?: (path: string) => void; +} + +export const AppRouter: React.StatelessComponent = ({ + history, + redirectTo = (path: string) => (window.location.href = path), + ...otherProps +}) => ( + + } + /> + +); diff --git a/src/core/public/application/ui/index.ts b/src/core/public/application/ui/index.ts new file mode 100644 index 0000000000000..7fa778740d3b4 --- /dev/null +++ b/src/core/public/application/ui/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 { AppRouter } from './app_router'; +export { AppNotFound } from './app_not_found_screen'; diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 74f2a09b895de..3775989c5126b 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -27,7 +27,7 @@ import { const createStartContractMock = () => { const startContract: DeeplyMockedKeys = { - getComponent: jest.fn(), + getHeaderComponent: jest.fn(), navLinks: { getNavLinks$: jest.fn(), has: jest.fn(), diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index 392846f8433ba..45e94040eeb4a 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -38,7 +38,7 @@ const store = new Map(); function defaultStartDeps() { return { - application: applicationServiceMock.createStartContract(), + application: applicationServiceMock.createInternalStartContract(), docLinks: docLinksServiceMock.createStartContract(), http: httpServiceMock.createStartContract(), injectedMetadata: injectedMetadataServiceMock.createStartContract(), @@ -87,7 +87,7 @@ Array [ const start = await service.start(defaultStartDeps()); // Have to do some fanagling to get the type system and enzyme to accept this. // Don't capture the snapshot because it's 600+ lines long. - expect(shallow(React.createElement(() => start.getComponent()))).toBeDefined(); + expect(shallow(React.createElement(() => start.getHeaderComponent()))).toBeDefined(); }); }); diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 668bce522bf4e..02195c794d280 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React from 'react'; +import React, { MouseEventHandler } from 'react'; import { BehaviorSubject, Observable, ReplaySubject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import * as Url from 'url'; @@ -27,13 +27,13 @@ import { IconType } from '@elastic/eui'; import { InjectedMetadataStart } from '../injected_metadata'; import { NotificationsStart } from '../notifications'; -import { ApplicationStart } from '../application'; +import { InternalApplicationStart } from '../application'; import { HttpStart } from '../http'; import { ChromeNavLinks, NavLinksService } from './nav_links'; import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed'; import { NavControlsService, ChromeNavControls } from './nav_controls'; -import { LoadingIndicator, Header } from './ui'; +import { LoadingIndicator, HeaderWrapper as Header } from './ui'; import { DocLinksStart } from '../doc_links'; export { ChromeNavControls, ChromeRecentlyAccessed }; @@ -63,6 +63,7 @@ export interface ChromeBreadcrumb { text: string; href?: string; 'data-test-subj'?: string; + onClick?: MouseEventHandler; } /** @public */ @@ -73,7 +74,7 @@ interface ConstructorParams { } interface StartDeps { - application: ApplicationStart; + application: InternalApplicationStart; docLinks: DocLinksStart; http: HttpStart; injectedMetadata: InjectedMetadataStart; @@ -83,14 +84,11 @@ interface StartDeps { /** @internal */ export class ChromeService { private readonly stop$ = new ReplaySubject(1); - private readonly browserSupportsCsp: boolean; private readonly navControls = new NavControlsService(); private readonly navLinks = new NavLinksService(); private readonly recentlyAccessed = new RecentlyAccessedService(); - constructor({ browserSupportsCsp }: ConstructorParams) { - this.browserSupportsCsp = browserSupportsCsp; - } + constructor(private readonly params: ConstructorParams) {} public async start({ application, @@ -114,7 +112,7 @@ export class ChromeService { const navLinks = this.navLinks.start({ application, http }); const recentlyAccessed = await this.recentlyAccessed.start({ http }); - if (!this.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { + if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { notifications.toasts.addWarning( i18n.translate('core.chrome.legacyBrowserWarning', { defaultMessage: 'Your browser does not meet the security requirements for Kibana.', @@ -127,31 +125,31 @@ export class ChromeService { navLinks, recentlyAccessed, - getComponent: () => ( + getHeaderComponent: () => ( -
-
(FORCE_HIDDEN ? false : visibility)), - takeUntil(this.stop$) - )} - kibanaVersion={injectedMetadata.getKibanaVersion()} - navLinks$={navLinks.getNavLinks$()} - recentlyAccessed$={recentlyAccessed.get$()} - navControlsLeft$={navControls.getLeft$()} - navControlsRight$={navControls.getRight$()} - /> -
+
(FORCE_HIDDEN ? false : visibility)), + takeUntil(this.stop$) + )} + kibanaVersion={injectedMetadata.getKibanaVersion()} + legacyMode={injectedMetadata.getLegacyMode()} + navLinks$={navLinks.getNavLinks$()} + recentlyAccessed$={recentlyAccessed.get$()} + navControlsLeft$={navControls.getLeft$()} + navControlsRight$={navControls.getRight$()} + /> ), @@ -375,5 +373,5 @@ export interface InternalChromeStart extends ChromeStart { * Used only by MountingService to render the header UI * @internal */ - getComponent(): JSX.Element; + getHeaderComponent(): JSX.Element; } diff --git a/src/core/public/chrome/nav_links/nav_link.ts b/src/core/public/chrome/nav_links/nav_link.ts index b323bf5318b23..d87d171e028e1 100644 --- a/src/core/public/chrome/nav_links/nav_link.ts +++ b/src/core/public/chrome/nav_links/nav_link.ts @@ -28,11 +28,6 @@ export interface ChromeNavLink { */ readonly id: string; - /** - * An ordinal used to sort nav links relative to one another for display. - */ - readonly order: number; - /** * The title of the application. */ @@ -43,6 +38,11 @@ export interface ChromeNavLink { */ readonly baseUrl: string; + /** + * An ordinal used to sort nav links relative to one another for display. + */ + readonly order?: number; + /** * A tooltip shown when hovering over an app link. */ diff --git a/src/core/public/chrome/nav_links/nav_links_service.test.ts b/src/core/public/chrome/nav_links/nav_links_service.test.ts index dfef8dc7989f6..8c135b3c4c49f 100644 --- a/src/core/public/chrome/nav_links/nav_links_service.test.ts +++ b/src/core/public/chrome/nav_links/nav_links_service.test.ts @@ -19,20 +19,27 @@ import { NavLinksService } from './nav_links_service'; import { take, map, takeLast } from 'rxjs/operators'; +import { LegacyApp } from '../../application'; const mockAppService = { - availableApps: [], - availableLegacyApps: [ - { id: 'legacyApp1', order: 0, title: 'Legacy App 1', icon: 'legacyApp1', appUrl: '/app1' }, - { - id: 'legacyApp2', - order: -10, - title: 'Legacy App 2', - euiIconType: 'canvasApp', - appUrl: '/app2', - }, - { id: 'legacyApp3', order: 20, title: 'Legacy App 3', appUrl: '/app3' }, - ], + availableApps: new Map(), + availableLegacyApps: new Map([ + [ + 'legacyApp1', + { id: 'legacyApp1', order: 0, title: 'Legacy App 1', icon: 'legacyApp1', appUrl: '/app1' }, + ], + [ + 'legacyApp2', + { + id: 'legacyApp2', + order: -10, + title: 'Legacy App 2', + euiIconType: 'canvasApp', + appUrl: '/app2', + }, + ], + ['legacyApp3', { id: 'legacyApp3', order: 20, title: 'Legacy App 3', appUrl: '/app3' }], + ]), } as any; const mockHttp = { diff --git a/src/core/public/chrome/nav_links/nav_links_service.ts b/src/core/public/chrome/nav_links/nav_links_service.ts index 2250ec40f0f44..affc639faf0b8 100644 --- a/src/core/public/chrome/nav_links/nav_links_service.ts +++ b/src/core/public/chrome/nav_links/nav_links_service.ts @@ -21,11 +21,11 @@ import { sortBy } from 'lodash'; import { BehaviorSubject, ReplaySubject, Observable } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { NavLinkWrapper, ChromeNavLinkUpdateableFields, ChromeNavLink } from './nav_link'; -import { ApplicationStart } from '../../application'; +import { InternalApplicationStart } from '../../application'; import { HttpStart } from '../../http'; interface StartDeps { - application: ApplicationStart; + application: InternalApplicationStart; http: HttpStart; } @@ -99,10 +99,22 @@ export class NavLinksService { private readonly stop$ = new ReplaySubject(1); public start({ application, http }: StartDeps): ChromeNavLinks { - const legacyAppLinks = application.availableLegacyApps.map( - app => + const appLinks = [...application.availableApps].map( + ([appId, app]) => [ - app.id, + appId, + new NavLinkWrapper({ + ...app, + legacy: false, + baseUrl: relativeToAbsolute(http.basePath.prepend(`/app/${appId}`)), + }), + ] as [string, NavLinkWrapper] + ); + + const legacyAppLinks = [...application.availableLegacyApps].map( + ([appId, app]) => + [ + appId, new NavLinkWrapper({ ...app, legacy: true, @@ -112,7 +124,7 @@ export class NavLinksService { ); const navLinks$ = new BehaviorSubject>( - new Map(legacyAppLinks) + new Map([...legacyAppLinks, ...appLinks]) ); const forceAppSwitcherNavigation$ = new BehaviorSubject(false); diff --git a/src/core/public/chrome/ui/header/_index.scss b/src/core/public/chrome/ui/header/_index.scss index 2b841eca6e01d..f19728a52dd70 100644 --- a/src/core/public/chrome/ui/header/_index.scss +++ b/src/core/public/chrome/ui/header/_index.scss @@ -1,13 +1,14 @@ @import '@elastic/eui/src/components/header/variables'; +@import '@elastic/eui/src/components/nav_drawer/variables'; -.header-global-wrapper { +.chrHeaderWrapper { width: 100%; position: fixed; top: 0; z-index: 10; } -.header-global-wrapper + .app-wrapper:not(.hidden-chrome) { +.chrHeaderWrapper ~ .app-wrapper:not(.hidden-chrome) { top: $euiHeaderChildSize; left: $euiHeaderChildSize; @@ -19,13 +20,6 @@ } } -// Mobile header is smaller -@include euiBreakpoint('xs', 's') { - .header-global-wrapper + .app-wrapper:not(.hidden-chrome) { - left: 0; - } -} - .chrHeaderHelpMenu__version { text-transform: none; } @@ -34,3 +28,20 @@ align-self: center; margin-right: $euiSize; } + +// Mobile header is smaller +@include euiBreakpoint('xs', 's') { + .chrHeaderWrapper ~ .app-wrapper:not(.hidden-chrome) { + left: 0; + } +} + +@include euiBreakpoint('xl') { + .chrHeaderWrapper--navIsLocked { + ~ .app-wrapper:not(.hidden-chrome) { + // Shrink the content from the left so it's no longer overlapped by the nav drawer (ALWAYS) + left: $euiNavDrawerWidthExpanded !important; // sass-lint:disable-line no-important + transition: left $euiAnimSpeedFast $euiAnimSlightResistance; + } + } +} diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 04c1a11824870..afd9f8e4a3820 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -65,6 +65,7 @@ import { } from '../..'; import { HttpStart } from '../../../http'; import { ChromeHelpExtension } from '../../chrome_service'; +import { ApplicationStart, InternalApplicationStart } from '../../../application/types'; // Providing a buffer between the limit and the cut off index // protects from truncating just the last couple (6) characters @@ -115,13 +116,24 @@ function extendRecentlyAccessedHistoryItem( }; } -function extendNavLink(navLink: ChromeNavLink) { +function extendNavLink(navLink: ChromeNavLink, urlForApp: ApplicationStart['getUrlForApp']) { + if (navLink.legacy) { + return { + ...navLink, + href: navLink.url && !navLink.active ? navLink.url : navLink.baseUrl, + }; + } + return { ...navLink, - href: navLink.url && !navLink.active ? navLink.url : navLink.baseUrl, + href: urlForApp(navLink.id), }; } +function isModifiedEvent(event: MouseEvent) { + return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); +} + function findClosestAnchor(element: HTMLElement): HTMLAnchorElement | void { let current = element; while (current) { @@ -149,6 +161,7 @@ export type HeaderProps = Pick>; interface Props { kibanaVersion: string; + application: InternalApplicationStart; appTitle$: Rx.Observable; badge$: Rx.Observable; breadcrumbs$: Rx.Observable; @@ -159,14 +172,18 @@ interface Props { recentlyAccessed$: Rx.Observable; forceAppSwitcherNavigation$: Rx.Observable; helpExtension$: Rx.Observable; + legacyMode: boolean; navControlsLeft$: Rx.Observable; navControlsRight$: Rx.Observable; intl: InjectedIntl; basePath: HttpStart['basePath']; + isLocked?: boolean; + onIsLockedUpdate?: (isLocked: boolean) => void; } interface State { appTitle: string; + currentAppId?: string; isVisible: boolean; navLinks: ReadonlyArray>; recentlyAccessed: ReadonlyArray>; @@ -201,7 +218,11 @@ class HeaderUI extends Component { this.props.navLinks$, this.props.recentlyAccessed$, // Types for combineLatest only handle up to 6 inferred types so we combine these two separately. - Rx.combineLatest(this.props.navControlsLeft$, this.props.navControlsRight$) + Rx.combineLatest( + this.props.navControlsLeft$, + this.props.navControlsRight$, + this.props.application.currentAppId$ + ) ).subscribe({ next: ([ appTitle, @@ -209,18 +230,21 @@ class HeaderUI extends Component { forceNavigation, navLinks, recentlyAccessed, - [navControlsLeft, navControlsRight], + [navControlsLeft, navControlsRight, currentAppId], ]) => { this.setState({ appTitle, isVisible, forceNavigation, - navLinks: navLinks.map(navLink => extendNavLink(navLink)), + navLinks: navLinks.map(navLink => + extendNavLink(navLink, this.props.application.getUrlForApp) + ), recentlyAccessed: recentlyAccessed.map(ra => extendRecentlyAccessedHistoryItem(navLinks, ra, this.props.basePath) ), navControlsLeft, navControlsRight, + currentAppId, }); }, }); @@ -261,16 +285,21 @@ class HeaderUI extends Component { public render() { const { + application, badge$, basePath, breadcrumbs$, helpExtension$, intl, + isLocked, kibanaDocLink, kibanaVersion, + onIsLockedUpdate, + legacyMode, } = this.props; const { appTitle, + currentAppId, isVisible, navControlsLeft, navControlsRight, @@ -287,9 +316,26 @@ class HeaderUI extends Component { .map(navLink => ({ key: navLink.id, label: navLink.title, + + // Use href and onClick to support "open in new tab" and SPA navigation in the same link href: navLink.href, + onClick: (event: MouseEvent) => { + if ( + !legacyMode && // ignore when in legacy mode + !navLink.legacy && // ignore links to legacy apps + !event.defaultPrevented && // onClick prevented default + event.button === 0 && // ignore everything but left clicks + !isModifiedEvent(event) // ignore clicks with modifier keys + ) { + event.preventDefault(); + application.navigateToApp(navLink.id); + } + }, + + // Legacy apps use `active` property, NP apps should match the current app + isActive: navLink.active || currentAppId === navLink.id, isDisabled: navLink.disabled, - isActive: navLink.active, + iconType: navLink.euiIconType, icon: !navLink.euiIconType && navLink.icon ? ( @@ -355,7 +401,12 @@ class HeaderUI extends Component { - + diff --git a/src/core/public/chrome/ui/header/header_wrapper.tsx b/src/core/public/chrome/ui/header/header_wrapper.tsx new file mode 100644 index 0000000000000..5306faa209586 --- /dev/null +++ b/src/core/public/chrome/ui/header/header_wrapper.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, { FunctionComponent, useState } from 'react'; +import classnames from 'classnames'; +import { Header, HeaderProps } from './'; + +const IS_LOCKED_KEY = 'core.chrome.isLocked'; + +export const HeaderWrapper: FunctionComponent = props => { + const initialIsLocked = localStorage.getItem(IS_LOCKED_KEY); + const [isLocked, setIsLocked] = useState(initialIsLocked === 'true'); + const setIsLockedStored = (locked: boolean) => { + localStorage.setItem(IS_LOCKED_KEY, `${locked}`); + setIsLocked(locked); + }; + const className = classnames( + 'chrHeaderWrapper', + { + 'chrHeaderWrapper--navIsLocked': isLocked, + }, + 'hide-for-sharing' + ); + return ( +
+
+
+ ); +}; diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts index f4c7127b93bfb..f9c122b864dce 100644 --- a/src/core/public/chrome/ui/header/index.ts +++ b/src/core/public/chrome/ui/header/index.ts @@ -18,3 +18,4 @@ */ export { Header, HeaderProps } from './header'; +export { HeaderWrapper } from './header_wrapper'; diff --git a/src/core/public/chrome/ui/index.ts b/src/core/public/chrome/ui/index.ts index 0136f3e2b203d..69582f6f1ed52 100644 --- a/src/core/public/chrome/ui/index.ts +++ b/src/core/public/chrome/ui/index.ts @@ -18,4 +18,4 @@ */ export { LoadingIndicator } from './loading_indicator'; -export { Header } from './header'; +export { Header, HeaderWrapper } from './header'; diff --git a/src/core/public/core_system.test.ts b/src/core/public/core_system.test.ts index 7310a8f33eba4..895fc785b11b1 100644 --- a/src/core/public/core_system.test.ts +++ b/src/core/public/core_system.test.ts @@ -272,7 +272,9 @@ describe('#start()', () => { await startCore(); expect(MockRenderingService.start).toHaveBeenCalledTimes(1); expect(MockRenderingService.start).toHaveBeenCalledWith({ + application: expect.any(Object), chrome: expect.any(Object), + injectedMetadata: expect.any(Object), targetDomElement: expect.any(HTMLElement), }); }); @@ -364,7 +366,7 @@ describe('LegacyPlatformService targetDomElement', () => { it('only mounts the element when start, after setting up the legacyPlatformService', async () => { const core = createCoreSystem(); - let targetDomElementInStart: HTMLElement | null; + let targetDomElementInStart: HTMLElement | undefined; MockLegacyPlatformService.start.mockImplementation(({ targetDomElement }) => { targetDomElementInStart = targetDomElement; }); diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 7782c93c7bbb1..4eb16572d8fec 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -20,23 +20,29 @@ import './core.css'; import { CoreId } from '../server'; -import { InternalCoreSetup, InternalCoreStart } from '.'; +import { CoreSetup, CoreStart } from '.'; import { ChromeService } from './chrome'; import { FatalErrorsService, FatalErrorsSetup } from './fatal_errors'; import { HttpService } from './http'; import { I18nService } from './i18n'; -import { InjectedMetadataParams, InjectedMetadataService } from './injected_metadata'; +import { + InjectedMetadataParams, + InjectedMetadataService, + InjectedMetadataSetup, + InjectedMetadataStart, +} from './injected_metadata'; import { LegacyPlatformParams, LegacyPlatformService } from './legacy'; import { NotificationsService } from './notifications'; import { OverlayService } from './overlays'; import { PluginsService } from './plugins'; import { UiSettingsService } from './ui_settings'; import { ApplicationService } from './application'; -import { mapToObject } from '../utils/'; +import { mapToObject, pick } from '../utils/'; import { DocLinksService } from './doc_links'; import { RenderingService } from './rendering'; import { SavedObjectsService } from './saved_objects/saved_objects_service'; import { ContextService } from './context'; +import { InternalApplicationSetup, InternalApplicationStart } from './application/types'; interface Params { rootDomElement: HTMLElement; @@ -51,6 +57,18 @@ export interface CoreContext { coreId: CoreId; } +/** @internal */ +export interface InternalCoreSetup extends Omit { + application: InternalApplicationSetup; + injectedMetadata: InjectedMetadataSetup; +} + +/** @internal */ +export interface InternalCoreStart extends Omit { + application: InternalApplicationStart; + injectedMetadata: InjectedMetadataStart; +} + /** * The CoreSystem is the root of the new platform, and setups all parts * of Kibana in the UI, including the LegacyPlatform which is managed @@ -77,6 +95,7 @@ export class CoreSystem { private readonly context: ContextService; private readonly rootDomElement: HTMLElement; + private readonly coreContext: CoreContext; private fatalErrorsSetup: FatalErrorsSetup | null = null; constructor(params: Params) { @@ -106,14 +125,14 @@ export class CoreSystem { this.savedObjects = new SavedObjectsService(); this.uiSettings = new UiSettingsService(); this.overlay = new OverlayService(); - this.application = new ApplicationService(); this.chrome = new ChromeService({ browserSupportsCsp }); this.docLinks = new DocLinksService(); this.rendering = new RenderingService(); + this.application = new ApplicationService(); - const core: CoreContext = { coreId: Symbol('core') }; - this.context = new ContextService(core); - this.plugins = new PluginsService(core, injectedMetadata.uiPlugins); + this.coreContext = { coreId: Symbol('core') }; + this.context = new ContextService(this.coreContext); + this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins); this.legacyPlatform = new LegacyPlatformService({ requireLegacyFiles, @@ -133,10 +152,10 @@ export class CoreSystem { const http = this.http.setup({ injectedMetadata, fatalErrors: this.fatalErrorsSetup }); const uiSettings = this.uiSettings.setup({ http, injectedMetadata }); const notifications = this.notifications.setup({ uiSettings }); - const application = this.application.setup(); const pluginDependencies = this.plugins.getOpaqueIds(); const context = this.context.setup({ pluginDependencies }); + const application = this.application.setup({ context }); const core: InternalCoreSetup = { application, @@ -150,7 +169,11 @@ export class CoreSystem { // Services that do not expose contracts at setup const plugins = await this.plugins.setup(core); - await this.legacyPlatform.setup({ core, plugins: mapToObject(plugins.contracts) }); + + await this.legacyPlatform.setup({ + core, + plugins: mapToObject(plugins.contracts), + }); return { fatalErrors: this.fatalErrorsSetup }; } catch (error) { @@ -171,7 +194,7 @@ export class CoreSystem { const http = await this.http.start({ injectedMetadata, fatalErrors: this.fatalErrorsSetup }); const savedObjects = await this.savedObjects.start({ http }); const i18n = await this.i18n.start(); - const application = await this.application.start({ injectedMetadata }); + const application = await this.application.start({ http, injectedMetadata }); const coreUiTargetDomElement = document.createElement('div'); coreUiTargetDomElement.id = 'kibana-body'; @@ -200,6 +223,17 @@ export class CoreSystem { }); const uiSettings = await this.uiSettings.start(); + application.registerMountContext(this.coreContext.coreId, 'core', () => ({ + application: pick(application, ['capabilities', 'navigateToApp']), + chrome, + docLinks, + http, + i18n, + notifications, + overlays, + uiSettings, + })); + const core: InternalCoreStart = { application, chrome, @@ -215,9 +249,12 @@ export class CoreSystem { const plugins = await this.plugins.start(core); const rendering = this.rendering.start({ + application, chrome, + injectedMetadata, targetDomElement: coreUiTargetDomElement, }); + await this.legacyPlatform.start({ core, plugins: mapToObject(plugins.contracts), diff --git a/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap b/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap index c6912764db2af..197516205cbe9 100644 --- a/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap +++ b/src/core/public/fatal_errors/__snapshots__/fatal_errors_screen.test.tsx.snap @@ -24,10 +24,7 @@ exports[`rendering render matches snapshot 1`] = ` color="primary" data-test-subj="clearSession" fill={true} - iconSide="left" onClick={[Function]} - size="m" - type="button" > , & { basePath: jest.Mocked; }; -const createServiceMock = (): ServiceSetupMockType => ({ +const createServiceMock = ({ basePath = '' } = {}): ServiceSetupMockType => ({ fetch: jest.fn(), get: jest.fn(), head: jest.fn(), @@ -35,8 +35,8 @@ const createServiceMock = (): ServiceSetupMockType => ({ delete: jest.fn(), options: jest.fn(), basePath: { - get: jest.fn(), - prepend: jest.fn(), + get: jest.fn(() => basePath), + prepend: jest.fn(path => `${basePath}${path}`), remove: jest.fn(), }, addLoadingCount: jest.fn(), @@ -46,22 +46,19 @@ const createServiceMock = (): ServiceSetupMockType => ({ removeAllInterceptors: jest.fn(), }); -const createSetupContractMock = createServiceMock; -const createStartContractMock = createServiceMock; - -const createMock = () => { +const createMock = ({ basePath = '' } = {}) => { const mocked: jest.Mocked> = { setup: jest.fn(), start: jest.fn(), stop: jest.fn(), }; - mocked.setup.mockReturnValue(createSetupContractMock()); - mocked.start.mockReturnValue(createSetupContractMock()); + mocked.setup.mockReturnValue(createServiceMock({ basePath })); + mocked.start.mockReturnValue(createServiceMock({ basePath })); return mocked; }; export const httpServiceMock = { create: createMock, - createSetupContract: createSetupContractMock, - createStartContract: createStartContractMock, + createSetupContract: createServiceMock, + createStartContract: createServiceMock, }; diff --git a/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap b/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap index 0910635924ea2..d159c588718fe 100644 --- a/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap +++ b/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap @@ -54,8 +54,14 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiStepNumber.hasErrors": "has errors", "euiStepNumber.hasWarnings": "has warnings", "euiStepNumber.isComplete": "complete", + "euiSuperDatePicker.showDatesButtonLabel": "Show dates", "euiSuperSelect.screenReaderAnnouncement": [Function], "euiSuperSelectControl.selectAnOption": [Function], + "euiSuperUpdateButton.cannotUpdateTooltip": "Cannot update", + "euiSuperUpdateButton.clickToApplyTooltip": "Click to apply", + "euiSuperUpdateButton.refreshButtonLabel": "Refresh", + "euiSuperUpdateButton.updateButtonLabel": "Update", + "euiSuperUpdateButton.updatingButtonLabel": "Updating", "euiTablePagination.rowsPerPage": "Rows per page", "euiTablePagination.rowsPerPageOption": [Function], "euiTableSortMobile.sorting": "Sorting", diff --git a/src/core/public/i18n/i18n_service.tsx b/src/core/public/i18n/i18n_service.tsx index 78411a7a418d7..17cdf56cd43c0 100644 --- a/src/core/public/i18n/i18n_service.tsx +++ b/src/core/public/i18n/i18n_service.tsx @@ -285,6 +285,13 @@ export class I18nService { description: 'Used as the title attribute on an image or svg icon to indicate a given process step is complete', }), + '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: @@ -296,6 +303,41 @@ export class I18nService { 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', diff --git a/src/core/public/index.ts b/src/core/public/index.ts index abc922ff97c1d..89c309d8427d7 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -71,6 +71,9 @@ import { IContextContainer, IContextProvider, ContextSetup, IContextHandler } fr export { CoreContext, CoreSystem } from './core_system'; export { RecursiveReadonly } from '../utils'; + +export { App, AppBase, AppUnmount, AppMountContext, AppMountParameters } from './application'; + export { SavedObjectsBatchResponse, SavedObjectsBulkCreateObject, @@ -114,6 +117,8 @@ export { * https://github.com/Microsoft/web-build-tools/issues/1237 */ export interface CoreSetup { + /** {@link ApplicationSetup} */ + application: ApplicationSetup; /** {@link ContextSetup} */ context: ContextSetup; /** {@link FatalErrorsSetup} */ @@ -137,7 +142,7 @@ export interface CoreSetup { */ export interface CoreStart { /** {@link ApplicationStart} */ - application: Pick; + application: ApplicationStart; /** {@link ChromeStart} */ chrome: ChromeStart; /** {@link DocLinksStart} */ @@ -156,15 +161,33 @@ export interface CoreStart { uiSettings: UiSettingsClientContract; } -/** @internal */ -export interface InternalCoreSetup extends CoreSetup { - application: ApplicationSetup; +/** + * Setup interface exposed to the legacy platform via the `ui/new_platform` module. + * + * @remarks + * Some methods are not supported in the legacy platform and while present to make this type compatibile with + * {@link CoreSetup}, unsupported methods will throw exceptions when called. + * + * @public + * @deprecated + */ +export interface LegacyCoreSetup extends CoreSetup { + /** @deprecated */ injectedMetadata: InjectedMetadataSetup; } -/** @internal */ -export interface InternalCoreStart extends CoreStart { - application: ApplicationStart; +/** + * Start interface exposed to the legacy platform via the `ui/new_platform` module. + * + * @remarks + * Some methods are not supported in the legacy platform and while present to make this type compatibile with + * {@link CoreStart}, unsupported methods will throw exceptions when called. + * + * @public + * @deprecated + */ +export interface LegacyCoreStart extends CoreStart { + /** @deprecated */ injectedMetadata: InjectedMetadataStart; } diff --git a/src/core/public/injected_metadata/injected_metadata_service.mock.ts b/src/core/public/injected_metadata/injected_metadata_service.mock.ts index c4579bee3f131..9e1d5aeec7ff4 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.mock.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.mock.ts @@ -25,6 +25,7 @@ const createSetupContractMock = () => { getKibanaBranch: jest.fn(), getCapabilities: jest.fn(), getCspConfig: jest.fn(), + getLegacyMode: jest.fn(), getLegacyMetadata: jest.fn(), getPlugins: jest.fn(), getInjectedVar: jest.fn(), @@ -34,6 +35,7 @@ const createSetupContractMock = () => { setupContract.getCapabilities.mockReturnValue({} as any); setupContract.getCspConfig.mockReturnValue({ warnLegacyBrowsers: true }); setupContract.getKibanaVersion.mockReturnValue('kibanaVersion'); + setupContract.getLegacyMode.mockReturnValue(true); setupContract.getLegacyMetadata.mockReturnValue({ nav: [], uiSettings: { diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 9fbc955485512..aa9d2a1458735 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -51,9 +51,9 @@ export interface InjectedMetadataParams { plugin: DiscoveredPlugin; }>; capabilities: Capabilities; + legacyMode: boolean; legacyMetadata: { app: unknown; - translations: unknown; bundleId: string; nav: LegacyNavLink[]; version: string; @@ -112,6 +112,10 @@ export class InjectedMetadataService { return this.state.uiPlugins; }, + getLegacyMode: () => { + return this.state.legacyMode; + }, + getLegacyMetadata: () => { return this.state.legacyMetadata; }, @@ -156,9 +160,10 @@ export interface InjectedMetadataSetup { id: string; plugin: DiscoveredPlugin; }>; + /** Indicates whether or not we are rendering a known legacy app. */ + getLegacyMode: () => boolean; getLegacyMetadata: () => { app: unknown; - translations: unknown; bundleId: string; nav: LegacyNavLink[]; version: string; diff --git a/src/core/public/legacy/legacy_service.test.ts b/src/core/public/legacy/legacy_service.test.ts index eb5b3e90f1a52..37e07af0a7da5 100644 --- a/src/core/public/legacy/legacy_service.test.ts +++ b/src/core/public/legacy/legacy_service.test.ts @@ -61,7 +61,7 @@ import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { savedObjectsMock } from '../saved_objects/saved_objects_service.mock'; import { contextServiceMock } from '../context/context_service.mock'; -const applicationSetup = applicationServiceMock.createSetupContract(); +const applicationSetup = applicationServiceMock.createInternalSetupContract(); const contextSetup = contextServiceMock.createSetupContract(); const fatalErrorsSetup = fatalErrorsServiceMock.createSetupContract(); const httpSetup = httpServiceMock.createSetupContract(); @@ -88,7 +88,7 @@ const defaultSetupDeps = { plugins: {}, }; -const applicationStart = applicationServiceMock.createStartContract(); +const applicationStart = applicationServiceMock.createInternalStartContract(); const docLinksStart = docLinksServiceMock.createStartContract(); const httpStart = httpServiceMock.createStartContract(); const chromeStart = chromeServiceMock.createStartContract(); @@ -98,6 +98,7 @@ const notificationsStart = notificationServiceMock.createStartContract(); const overlayStart = overlayServiceMock.createStartContract(); const uiSettingsStart = uiSettingsServiceMock.createStartContract(); const savedObjectsStart = savedObjectsMock.createStartContract(); +const mockStorage = { getItem: jest.fn() } as any; const defaultStartDeps = { core: { @@ -112,6 +113,7 @@ const defaultStartDeps = { uiSettings: uiSettingsStart, savedObjects: savedObjectsStart, }, + lastSubUrlStorage: mockStorage, targetDomElement: document.createElement('div'), plugins: {}, }; @@ -132,12 +134,29 @@ describe('#setup()', () => { legacyPlatform.setup(defaultSetupDeps); expect(mockUiNewPlatformSetup).toHaveBeenCalledTimes(1); - expect(mockUiNewPlatformSetup).toHaveBeenCalledWith(defaultSetupDeps.core, {}); + expect(mockUiNewPlatformSetup).toHaveBeenCalledWith(expect.any(Object), {}); }); }); }); describe('#start()', () => { + it('fetches and sets legacy lastSubUrls', () => { + chromeStart.navLinks.getAll.mockReturnValue([ + { id: 'link1', baseUrl: 'http://wowza.com/app1', legacy: true } as any, + ]); + mockStorage.getItem.mockReturnValue('http://wowza.com/app1/subUrl'); + const legacyPlatform = new LegacyPlatformService({ + ...defaultParams, + }); + + legacyPlatform.setup(defaultSetupDeps); + legacyPlatform.start({ ...defaultStartDeps, lastSubUrlStorage: mockStorage }); + + expect(chromeStart.navLinks.update).toHaveBeenCalledWith('link1', { + url: 'http://wowza.com/app1/subUrl', + }); + }); + it('initializes ui/new_platform with core APIs', () => { const legacyPlatform = new LegacyPlatformService({ ...defaultParams, @@ -147,7 +166,7 @@ describe('#start()', () => { legacyPlatform.start(defaultStartDeps); expect(mockUiNewPlatformStart).toHaveBeenCalledTimes(1); - expect(mockUiNewPlatformStart).toHaveBeenCalledWith(defaultStartDeps.core, {}); + expect(mockUiNewPlatformStart).toHaveBeenCalledWith(expect.any(Object), {}); }); describe('useLegacyTestHarness = false', () => { diff --git a/src/core/public/legacy/legacy_service.ts b/src/core/public/legacy/legacy_service.ts index 7d852773ad03f..ba93cd7b6b5a7 100644 --- a/src/core/public/legacy/legacy_service.ts +++ b/src/core/public/legacy/legacy_service.ts @@ -18,7 +18,8 @@ */ import angular from 'angular'; -import { InternalCoreSetup, InternalCoreStart } from '../'; +import { InternalCoreSetup, InternalCoreStart } from '../core_system'; +import { LegacyCoreSetup, LegacyCoreStart } from '../'; /** @internal */ export interface LegacyPlatformParams { @@ -34,7 +35,8 @@ interface SetupDeps { interface StartDeps { core: InternalCoreStart; plugins: Record; - targetDomElement: HTMLElement; + lastSubUrlStorage?: Storage; + targetDomElement?: HTMLElement; } interface BootstrapModule { @@ -55,10 +57,7 @@ export class LegacyPlatformService { constructor(private readonly params: LegacyPlatformParams) {} public setup({ core, plugins }: SetupDeps) { - // Inject parts of the new platform into parts of the legacy platform - // so that legacy APIs/modules can mimic their new platform counterparts - require('ui/new_platform').__setup__(core, plugins); - + // Always register legacy apps, even if not in legacy mode. core.injectedMetadata.getLegacyMetadata().nav.forEach((navLink: any) => core.application.registerLegacyApp({ id: navLink.id, @@ -71,12 +70,57 @@ export class LegacyPlatformService { linkToLastSubUrl: navLink.linkToLastSubUrl, }) ); + + const legacyCore: LegacyCoreSetup = { + ...core, + application: { + register: notSupported(`core.application.register()`), + registerMountContext: notSupported(`core.application.registerMountContext()`), + }, + }; + + // Inject parts of the new platform into parts of the legacy platform + // so that legacy APIs/modules can mimic their new platform counterparts + if (core.injectedMetadata.getLegacyMode()) { + require('ui/new_platform').__setup__(legacyCore, plugins); + } } - public start({ core, targetDomElement, plugins }: StartDeps) { + public start({ + core, + targetDomElement, + plugins, + lastSubUrlStorage = window.sessionStorage, + }: StartDeps) { + // Initialize legacy sub urls + core.chrome.navLinks + .getAll() + .filter(link => link.legacy) + .forEach(navLink => { + const lastSubUrl = lastSubUrlStorage.getItem(`lastSubUrl:${navLink.baseUrl}`); + core.chrome.navLinks.update(navLink.id, { + url: lastSubUrl || navLink.url || navLink.baseUrl, + }); + }); + + // Only import and bootstrap legacy platform if we're in legacy mode. + if (!core.injectedMetadata.getLegacyMode()) { + return; + } + + const legacyCore: LegacyCoreStart = { + ...core, + application: { + capabilities: core.application.capabilities, + getUrlForApp: core.application.getUrlForApp, + navigateToApp: core.application.navigateToApp, + registerMountContext: notSupported(`core.application.registerMountContext()`), + }, + }; + // Inject parts of the new platform into parts of the legacy platform // so that legacy APIs/modules can mimic their new platform counterparts - require('ui/new_platform').__start__(core, plugins); + require('ui/new_platform').__start__(legacyCore, plugins); // Load the bootstrap module before loading the legacy platform files so that // the bootstrap module can modify the environment a bit first @@ -91,7 +135,8 @@ export class LegacyPlatformService { this.targetDomElement = targetDomElement; - this.bootstrapModule.bootstrap(this.targetDomElement); + // `targetDomElement` is always defined when in legacy mode + this.bootstrapModule.bootstrap(this.targetDomElement!); } public stop() { @@ -129,3 +174,7 @@ export class LegacyPlatformService { return require('ui/chrome'); } } + +const notSupported = (methodName: string) => (...args: any[]) => { + throw new Error(`${methodName} is not supported in the legacy platform.`); +}; diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index 0f3a01c793ae3..7c99f69d6fd7a 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -42,6 +42,7 @@ export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; function createCoreSetupMock() { const mock: MockedKeys = { + application: applicationServiceMock.createSetupContract(), context: contextServiceMock.createSetupContract(), fatalErrors: fatalErrorsServiceMock.createSetupContract(), http: httpServiceMock.createSetupContract(), diff --git a/src/core/public/notifications/toasts/__snapshots__/error_toast.test.tsx.snap b/src/core/public/notifications/toasts/__snapshots__/error_toast.test.tsx.snap index 22af4cebcf387..5723039a43e20 100644 --- a/src/core/public/notifications/toasts/__snapshots__/error_toast.test.tsx.snap +++ b/src/core/public/notifications/toasts/__snapshots__/error_toast.test.tsx.snap @@ -12,11 +12,8 @@ exports[`renders matching snapshot 1`] = ` > ): CoreSetup { return { - context: omit(deps.context, 'setCurrentPlugin'), + application: { + register: app => deps.application.register(plugin.opaqueId, app), + registerMountContext: (contextName, provider) => + deps.application.registerMountContext(plugin.opaqueId, contextName, provider), + }, + context: deps.context, fatalErrors: deps.fatalErrors, http: deps.http, notifications: deps.notifications, @@ -107,6 +112,10 @@ export function createPluginStartContext< return { application: { capabilities: deps.application.capabilities, + navigateToApp: deps.application.navigateToApp, + getUrlForApp: deps.application.getUrlForApp, + registerMountContext: (contextName, provider) => + deps.application.registerMountContext(plugin.opaqueId, contextName, provider), }, docLinks: deps.docLinks, http: deps.http, diff --git a/src/core/public/plugins/plugin_loader.test.ts b/src/core/public/plugins/plugin_loader.test.ts index 14a82e9404db1..caa7b27773bf5 100644 --- a/src/core/public/plugins/plugin_loader.test.ts +++ b/src/core/public/plugins/plugin_loader.test.ts @@ -40,14 +40,12 @@ beforeEach(() => { appendChildSpy = jest.spyOn(document.body, 'appendChild').mockReturnValue({} as any); // Mock global fields needed for loading modules. - coreWindow.__kbnNonce__ = 'asdf'; coreWindow.__kbnBundles__ = {}; }); afterEach(() => { appendChildSpy.mockRestore(); createElementSpy.mockRestore(); - delete coreWindow.__kbnNonce__; delete coreWindow.__kbnBundles__; }); @@ -64,7 +62,6 @@ test('`loadPluginBundles` creates a script tag and loads initializer', async () '/bundles/plugin/plugin-a.bundle.js' ); expect(fakeScriptTag.setAttribute).toHaveBeenCalledWith('id', 'kbn-plugin-plugin-a'); - expect(fakeScriptTag.setAttribute).toHaveBeenCalledWith('nonce', 'asdf'); expect(fakeScriptTag.onload).toBeInstanceOf(Function); expect(fakeScriptTag.onerror).toBeInstanceOf(Function); expect(appendChildSpy).toHaveBeenCalledWith(fakeScriptTag); diff --git a/src/core/public/plugins/plugin_loader.ts b/src/core/public/plugins/plugin_loader.ts index 871091324a6b9..776ed7d7c5570 100644 --- a/src/core/public/plugins/plugin_loader.ts +++ b/src/core/public/plugins/plugin_loader.ts @@ -31,7 +31,6 @@ export type UnknownPluginInitializer = PluginInitializer { clearTimeout(timeout); // Set to null for IE memory leak issue. Webpack does the same thing. diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index 2b689e45b4f1a..d6411554e5f85 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -72,7 +72,7 @@ beforeEach(() => { }, ]; mockSetupDeps = { - application: applicationServiceMock.createSetupContract(), + application: applicationServiceMock.createInternalSetupContract(), context: contextServiceMock.createSetupContract(), fatalErrors: fatalErrorsServiceMock.createSetupContract(), http: httpServiceMock.createSetupContract(), @@ -81,10 +81,11 @@ beforeEach(() => { uiSettings: uiSettingsServiceMock.createSetupContract(), }; mockSetupContext = { - ...omit(mockSetupDeps, 'application', 'injectedMetadata'), + ...omit(mockSetupDeps, 'injectedMetadata'), + application: expect.any(Object), }; mockStartDeps = { - application: applicationServiceMock.createStartContract(), + application: applicationServiceMock.createInternalStartContract(), docLinks: docLinksServiceMock.createStartContract(), http: httpServiceMock.createStartContract(), chrome: chromeServiceMock.createStartContract(), @@ -97,9 +98,7 @@ beforeEach(() => { }; mockStartContext = { ...omit(mockStartDeps, 'injectedMetadata'), - application: { - capabilities: mockStartDeps.application.capabilities, - }, + application: expect.any(Object), chrome: omit(mockStartDeps.chrome, 'getComponent'), }; diff --git a/src/core/public/plugins/plugins_service.ts b/src/core/public/plugins/plugins_service.ts index 13a52d78d72fc..1ab9d7f2fa9b2 100644 --- a/src/core/public/plugins/plugins_service.ts +++ b/src/core/public/plugins/plugins_service.ts @@ -26,7 +26,7 @@ import { createPluginSetupContext, createPluginStartContext, } from './plugin_context'; -import { InternalCoreSetup, InternalCoreStart } from '..'; +import { InternalCoreSetup, InternalCoreStart } from '../core_system'; /** @internal */ export type PluginsServiceSetupDeps = InternalCoreSetup; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a5c31e41e0267..552476425d8d8 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -5,29 +5,71 @@ ```ts import { IconType } from '@elastic/eui'; +import { MouseEventHandler } from 'react'; import { Observable } from 'rxjs'; import React from 'react'; import * as Rx from 'rxjs'; import { EuiGlobalToastListToast as Toast } from '@elastic/eui'; +// @public +export interface App extends AppBase { + mount: (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise; +} + +// @public (undocumented) +export interface AppBase { + capabilities?: Partial; + euiIconType?: string; + icon?: string; + // (undocumented) + id: string; + order?: number; + title: string; + tooltip$?: Observable; +} + // @public (undocumented) export interface ApplicationSetup { - // Warning: (ae-forgotten-export) The symbol "App" needs to be exported by the entry point index.d.ts - registerApp(app: App): void; - // Warning: (ae-forgotten-export) The symbol "LegacyApp" needs to be exported by the entry point index.d.ts - // - // @internal - registerLegacyApp(app: LegacyApp): void; + register(app: App): void; + registerMountContext(contextName: T, provider: IContextProvider): void; } // @public (undocumented) export interface ApplicationStart { - availableApps: readonly App[]; - // @internal - availableLegacyApps: readonly LegacyApp[]; capabilities: RecursiveReadonly; + getUrlForApp(appId: string, options?: { + path?: string; + }): string; + navigateToApp(appId: string, options?: { + path?: string; + state?: any; + }): void; + registerMountContext(contextName: T, provider: IContextProvider): void; } +// @public +export interface AppMountContext { + core: { + application: Pick; + chrome: ChromeStart; + docLinks: DocLinksStart; + http: HttpStart; + i18n: I18nStart; + notifications: NotificationsStart; + overlays: OverlayStart; + uiSettings: UiSettingsClientContract; + }; +} + +// @public (undocumented) +export interface AppMountParameters { + appBasePath: string; + element: HTMLElement; +} + +// @public +export type AppUnmount = () => void; + // @public export interface Capabilities { [key: string]: Record>; @@ -63,6 +105,8 @@ export interface ChromeBreadcrumb { // (undocumented) href?: string; // (undocumented) + onClick?: MouseEventHandler; + // (undocumented) text: string; } @@ -102,7 +146,7 @@ export interface ChromeNavLink { readonly legacy: boolean; // @deprecated readonly linkToLastSubUrl?: boolean; - readonly order: number; + readonly order?: number; // @deprecated readonly subUrlBase?: string; readonly title: string; @@ -182,6 +226,8 @@ export interface CoreContext { // @public export interface CoreSetup { + // (undocumented) + application: ApplicationSetup; // (undocumented) context: ContextSetup; // (undocumented) @@ -197,7 +243,7 @@ export interface CoreSetup { // @public export interface CoreStart { // (undocumented) - application: Pick; + application: ApplicationStart; // (undocumented) chrome: ChromeStart; // (undocumented) @@ -502,23 +548,19 @@ export type IContextHandler, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName]; -// @internal (undocumented) -export interface InternalCoreSetup extends CoreSetup { - // (undocumented) - application: ApplicationSetup; +// @public @deprecated +export interface LegacyCoreSetup extends CoreSetup { // Warning: (ae-forgotten-export) The symbol "InjectedMetadataSetup" needs to be exported by the entry point index.d.ts // - // (undocumented) + // @deprecated (undocumented) injectedMetadata: InjectedMetadataSetup; } -// @internal (undocumented) -export interface InternalCoreStart extends CoreStart { - // (undocumented) - application: ApplicationStart; +// @public @deprecated +export interface LegacyCoreStart extends CoreStart { // Warning: (ae-forgotten-export) The symbol "InjectedMetadataStart" needs to be exported by the entry point index.d.ts // - // (undocumented) + // @deprecated (undocumented) injectedMetadata: InjectedMetadataStart; } diff --git a/src/core/public/rendering/rendering_service.test.tsx b/src/core/public/rendering/rendering_service.test.tsx index 5b4ab93996657..9a4b46c657f08 100644 --- a/src/core/public/rendering/rendering_service.test.tsx +++ b/src/core/public/rendering/rendering_service.test.tsx @@ -21,46 +21,67 @@ import React from 'react'; import { chromeServiceMock } from '../chrome/chrome_service.mock'; import { RenderingService } from './rendering_service'; +import { InternalApplicationStart } from '../application'; +import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; describe('RenderingService#start', () => { - const getService = () => { + const getService = ({ legacyMode = false }: { legacyMode?: boolean } = {}) => { const rendering = new RenderingService(); + const application = { + getComponent: () =>
Hello application!
, + } as InternalApplicationStart; const chrome = chromeServiceMock.createStartContract(); - chrome.getComponent.mockReturnValue(
Hello chrome!
); + chrome.getHeaderComponent.mockReturnValue(
Hello chrome!
); + const injectedMetadata = injectedMetadataServiceMock.createStartContract(); + injectedMetadata.getLegacyMode.mockReturnValue(legacyMode); const targetDomElement = document.createElement('div'); - const start = rendering.start({ chrome, targetDomElement }); + const start = rendering.start({ application, chrome, injectedMetadata, targetDomElement }); return { start, targetDomElement }; }; - it('renders into provided DOM element', () => { + it('renders application service into provided DOM element', () => { const { targetDomElement } = getService(); - expect(targetDomElement).toMatchInlineSnapshot(` -
-
-
- Hello chrome! -
-
-
-
-`); + expect(targetDomElement.querySelector('div.application')).toMatchInlineSnapshot(` +
+
+ Hello application! +
+
+ `); }); - it('returns a div for the legacy service to render into', () => { - const { - start: { legacyTargetDomElement }, - targetDomElement, - } = getService(); - legacyTargetDomElement.innerHTML = 'Hello legacy!'; - expect(targetDomElement.querySelector('#legacy')).toMatchInlineSnapshot(` - - Hello legacy! - -`); + it('contains wrapper divs', () => { + const { targetDomElement } = getService(); + expect(targetDomElement.querySelector('div.app-wrapper')).toBeDefined(); + expect(targetDomElement.querySelector('div.app-wrapper-pannel')).toBeDefined(); + }); + + describe('legacyMode', () => { + it('renders into provided DOM element', () => { + const { targetDomElement } = getService({ legacyMode: true }); + expect(targetDomElement).toMatchInlineSnapshot(` +
+
+
+ Hello chrome! +
+
+
+
+ `); + }); + + it('returns a div for the legacy service to render into', () => { + const { + start: { legacyTargetDomElement }, + targetDomElement, + } = getService({ legacyMode: true }); + expect(targetDomElement.contains(legacyTargetDomElement!)).toBe(true); + }); }); }); diff --git a/src/core/public/rendering/rendering_service.tsx b/src/core/public/rendering/rendering_service.tsx index cbb931bf59ef9..2e066feca8bf3 100644 --- a/src/core/public/rendering/rendering_service.tsx +++ b/src/core/public/rendering/rendering_service.tsx @@ -22,9 +22,13 @@ import ReactDOM from 'react-dom'; import { I18nProvider } from '@kbn/i18n/react'; import { InternalChromeStart } from '../chrome'; +import { InternalApplicationStart } from '../application'; +import { InjectedMetadataStart } from '../injected_metadata'; interface StartDeps { + application: InternalApplicationStart; chrome: InternalChromeStart; + injectedMetadata: InjectedMetadataStart; targetDomElement: HTMLDivElement; } @@ -39,28 +43,40 @@ interface StartDeps { * @internal */ export class RenderingService { - start({ chrome, targetDomElement }: StartDeps) { - const chromeUi = chrome.getComponent(); - const legacyRef = React.createRef(); + start({ application, chrome, injectedMetadata, targetDomElement }: StartDeps): RenderingStart { + const chromeUi = chrome.getHeaderComponent(); + const appUi = application.getComponent(); + + const legacyMode = injectedMetadata.getLegacyMode(); + const legacyRef = legacyMode ? React.createRef() : null; ReactDOM.render(
{chromeUi} -
+ {!legacyMode && ( +
+
+
{appUi}
+
+
+ )} + + {legacyMode &&
}
, targetDomElement ); return { - legacyTargetDomElement: legacyRef.current!, + // When in legacy mode, return legacy div, otherwise undefined. + legacyTargetDomElement: legacyRef ? legacyRef.current! : undefined, }; } } /** @internal */ export interface RenderingStart { - legacyTargetDomElement: HTMLDivElement; + legacyTargetDomElement?: HTMLDivElement; } diff --git a/src/core/server/http/__snapshots__/http_config.test.ts.snap b/src/core/server/http/__snapshots__/http_config.test.ts.snap index bdb65809d811c..57d9db5e8c1e4 100644 --- a/src/core/server/http/__snapshots__/http_config.test.ts.snap +++ b/src/core/server/http/__snapshots__/http_config.test.ts.snap @@ -45,6 +45,7 @@ Object { "!SRP", "!CAMELLIA", ], + "clientAuthentication": "none", "enabled": false, "supportedProtocols": Array [ "TLSv1.1", diff --git a/src/core/server/http/cookie_sesson_storage.test.ts b/src/core/server/http/cookie_sesson_storage.test.ts index 0c4973f70bd25..5cd2fbaa1ebe8 100644 --- a/src/core/server/http/cookie_sesson_storage.test.ts +++ b/src/core/server/http/cookie_sesson_storage.test.ts @@ -28,6 +28,7 @@ import { KibanaRequest } from './router'; import { Env } from '../config'; import { getEnvOptions } from '../config/__mocks__/env'; import { configServiceMock } from '../config/config_service.mock'; +import { contextServiceMock } from '../context/context_service.mock'; import { loggingServiceMock } from '../logging/logging_service.mock'; import { httpServerMock } from './http_server.mocks'; @@ -39,6 +40,11 @@ let logger: ReturnType; let env: Env; let coreContext: CoreContext; const configService = configServiceMock.create(); +const contextSetup = contextServiceMock.createSetupContract(); + +const setupDeps = { + context: contextSetup, +}; configService.atPath.mockReturnValue( new BehaviorSubject({ @@ -98,7 +104,7 @@ const cookieOptions = { describe('Cookie based SessionStorage', () => { describe('#set()', () => { it('Should write to session storage & set cookies', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter(''); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -132,7 +138,7 @@ describe('Cookie based SessionStorage', () => { }); describe('#get()', () => { it('reads from session storage', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter(''); router.get({ path: '/', validate: false }, async (context, req, res) => { @@ -140,9 +146,9 @@ describe('Cookie based SessionStorage', () => { const sessionValue = await sessionStorage.get(); if (!sessionValue) { sessionStorage.set({ value: userData, expires: Date.now() + sessionDurationMs }); - return res.ok({}); + return res.ok(); } - return res.ok({ value: sessionValue.value }); + return res.ok({ body: { value: sessionValue.value } }); }); const factory = await createCookieSessionStorageFactory( @@ -168,13 +174,13 @@ describe('Cookie based SessionStorage', () => { .expect(200, { value: userData }); }); it('returns null for empty session', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter(''); router.get({ path: '/', validate: false }, async (context, req, res) => { const sessionStorage = factory.asScoped(req); const sessionValue = await sessionStorage.get(); - return res.ok({ value: sessionValue }); + return res.ok({ body: { value: sessionValue } }); }); const factory = await createCookieSessionStorageFactory( @@ -193,7 +199,7 @@ describe('Cookie based SessionStorage', () => { }); it('returns null for invalid session & clean cookies', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter(''); @@ -203,10 +209,10 @@ describe('Cookie based SessionStorage', () => { if (!setOnce) { setOnce = true; sessionStorage.set({ value: userData, expires: Date.now() + sessionDurationMs }); - return res.ok({ value: userData }); + return res.ok({ body: { value: userData } }); } const sessionValue = await sessionStorage.get(); - return res.ok({ value: sessionValue }); + return res.ok({ body: { value: sessionValue } }); }); const factory = await createCookieSessionStorageFactory( @@ -326,7 +332,7 @@ describe('Cookie based SessionStorage', () => { describe('#clear()', () => { it('clears session storage & remove cookies', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter(''); diff --git a/src/core/server/http/http_config.test.ts b/src/core/server/http/http_config.test.ts index 11eec99a6f014..2b627c265dbba 100644 --- a/src/core/server/http/http_config.test.ts +++ b/src/core/server/http/http_config.test.ts @@ -17,7 +17,9 @@ * under the License. */ -import { config } from '.'; +import { config, HttpConfig } from '.'; +import { Env } from '../config'; +import { getEnvOptions } from '../config/__mocks__/env'; test('has defaults for config', () => { const httpSchema = config.schema; @@ -111,6 +113,46 @@ describe('with TLS', () => { expect(() => httpSchema.validate(obj)).toThrowErrorMatchingSnapshot(); }); + test('throws if TLS is not enabled but `clientAuthentication` is `optional`', () => { + const httpSchema = config.schema; + const obj = { + port: 1234, + ssl: { + enabled: false, + clientAuthentication: 'optional', + }, + }; + expect(() => httpSchema.validate(obj)).toThrowErrorMatchingInlineSnapshot( + `"[ssl]: must enable ssl to use [clientAuthentication]"` + ); + }); + + test('throws if TLS is not enabled but `clientAuthentication` is `required`', () => { + const httpSchema = config.schema; + const obj = { + port: 1234, + ssl: { + enabled: false, + clientAuthentication: 'required', + }, + }; + expect(() => httpSchema.validate(obj)).toThrowErrorMatchingInlineSnapshot( + `"[ssl]: must enable ssl to use [clientAuthentication]"` + ); + }); + + test('can specify `none` for [clientAuthentication] if ssl is not enabled', () => { + const obj = { + ssl: { + enabled: false, + clientAuthentication: 'none', + }, + }; + + const configValue = config.schema.validate(obj); + expect(configValue.ssl.clientAuthentication).toBe('none'); + }); + test('can specify single `certificateAuthority` as a string', () => { const obj = { ssl: { @@ -202,4 +244,55 @@ describe('with TLS', () => { httpSchema.validate(allKnownWithOneUnknownProtocols) ).toThrowErrorMatchingSnapshot(); }); + + test('HttpConfig instance should properly interpret `none` client authentication', () => { + const httpConfig = new HttpConfig( + config.schema.validate({ + ssl: { + enabled: true, + key: 'some-key-path', + certificate: 'some-certificate-path', + clientAuthentication: 'none', + }, + }), + Env.createDefault(getEnvOptions()) + ); + + expect(httpConfig.ssl.requestCert).toBe(false); + expect(httpConfig.ssl.rejectUnauthorized).toBe(false); + }); + + test('HttpConfig instance should properly interpret `optional` client authentication', () => { + const httpConfig = new HttpConfig( + config.schema.validate({ + ssl: { + enabled: true, + key: 'some-key-path', + certificate: 'some-certificate-path', + clientAuthentication: 'optional', + }, + }), + Env.createDefault(getEnvOptions()) + ); + + expect(httpConfig.ssl.requestCert).toBe(true); + expect(httpConfig.ssl.rejectUnauthorized).toBe(false); + }); + + test('HttpConfig instance should properly interpret `required` client authentication', () => { + const httpConfig = new HttpConfig( + config.schema.validate({ + ssl: { + enabled: true, + key: 'some-key-path', + certificate: 'some-certificate-path', + clientAuthentication: 'required', + }, + }), + Env.createDefault(getEnvOptions()) + ); + + expect(httpConfig.ssl.requestCert).toBe(true); + expect(httpConfig.ssl.rejectUnauthorized).toBe(true); + }); }); diff --git a/src/core/server/http/http_config.ts b/src/core/server/http/http_config.ts index f808a4e9032dd..a42d38fd4cb70 100644 --- a/src/core/server/http/http_config.ts +++ b/src/core/server/http/http_config.ts @@ -26,6 +26,8 @@ const validBasePathRegex = /(^$|^\/.*[^\/]$)/; const match = (regex: RegExp, errorMsg: string) => (str: string) => regex.test(str) ? undefined : errorMsg; +// before update to make sure it's in sync with validation rules in Legacy +// https://github.com/elastic/kibana/blob/master/src/legacy/server/config/schema.js export const config = { path: 'server', schema: schema.object( diff --git a/src/core/server/http/http_server.mocks.ts b/src/core/server/http/http_server.mocks.ts index 33a98127aa630..fcc232345a802 100644 --- a/src/core/server/http/http_server.mocks.ts +++ b/src/core/server/http/http_server.mocks.ts @@ -18,6 +18,7 @@ */ import { Request } from 'hapi'; import { merge } from 'lodash'; +import { Socket } from 'net'; import querystring from 'querystring'; @@ -37,6 +38,7 @@ interface RequestFixtureOptions { query?: Record; path?: string; method?: RouteMethod; + socket?: Socket; } function createKibanaRequestMock({ @@ -46,6 +48,7 @@ function createKibanaRequestMock({ body = {}, query = {}, method = 'get', + socket = new Socket(), }: RequestFixtureOptions = {}) { const queryString = querystring.stringify(query); return KibanaRequest.from( @@ -63,7 +66,7 @@ function createKibanaRequestMock({ }, route: { settings: {} }, raw: { - req: {}, + req: { socket }, }, } as any, { diff --git a/src/core/server/http/http_server.test.ts b/src/core/server/http/http_server.test.ts index 21a6490fb54ce..acae9d8ff0e70 100644 --- a/src/core/server/http/http_server.test.ts +++ b/src/core/server/http/http_server.test.ts @@ -44,6 +44,7 @@ let configWithSSL: HttpConfig; const loggingService = loggingServiceMock.create(); const logger = loggingService.get(); +const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {}); beforeEach(() => { config = { @@ -122,7 +123,7 @@ test('log listening address after started when configured with BasePath and rewr }); test('valid params', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.get( { @@ -134,7 +135,7 @@ test('valid params', async () => { }, }, (context, req, res) => { - return res.ok({ key: req.params.test }); + return res.ok({ body: req.params.test }); } ); @@ -147,12 +148,12 @@ test('valid params', async () => { .get('/foo/some-string') .expect(200) .then(res => { - expect(res.body).toEqual({ key: 'some-string' }); + expect(res.text).toBe('some-string'); }); }); test('invalid params', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.get( { @@ -164,7 +165,7 @@ test('invalid params', async () => { }, }, (context, req, res) => { - return res.ok({ key: req.params.test }); + return res.ok({ body: String(req.params.test) }); } ); @@ -186,7 +187,7 @@ test('invalid params', async () => { }); test('valid query', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.get( { @@ -199,7 +200,7 @@ test('valid query', async () => { }, }, (context, req, res) => { - return res.ok(req.query); + return res.ok({ body: req.query }); } ); @@ -217,7 +218,7 @@ test('valid query', async () => { }); test('invalid query', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.get( { @@ -229,7 +230,7 @@ test('invalid query', async () => { }, }, (context, req, res) => { - return res.ok(req.query); + return res.ok({ body: req.query }); } ); @@ -251,7 +252,7 @@ test('invalid query', async () => { }); test('valid body', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.post( { @@ -264,7 +265,7 @@ test('valid body', async () => { }, }, (context, req, res) => { - return res.ok(req.body); + return res.ok({ body: req.body }); } ); @@ -286,7 +287,7 @@ test('valid body', async () => { }); test('invalid body', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.post( { @@ -298,7 +299,7 @@ test('invalid body', async () => { }, }, (context, req, res) => { - return res.ok(req.body); + return res.ok({ body: req.body }); } ); @@ -321,7 +322,7 @@ test('invalid body', async () => { }); test('handles putting', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.put( { @@ -333,7 +334,7 @@ test('handles putting', async () => { }, }, (context, req, res) => { - return res.ok(req.body); + return res.ok({ body: req.body }); } ); @@ -352,7 +353,7 @@ test('handles putting', async () => { }); test('handles deleting', async () => { - const router = new Router('/foo', logger); + const router = new Router('/foo', logger, enhanceWithContext); router.delete( { @@ -364,7 +365,7 @@ test('handles deleting', async () => { }, }, (context, req, res) => { - return res.ok({ key: req.params.id }); + return res.ok({ body: { key: req.params.id } }); } ); @@ -392,10 +393,10 @@ describe('with `basepath: /bar` and `rewriteBasePath: false`', () => { rewriteBasePath: false, } as HttpConfig; - const router = new Router('/', logger); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ key: 'value:/' })); + const router = new Router('/', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: 'value:/' })); router.get({ path: '/foo', validate: false }, (context, req, res) => - res.ok({ key: 'value:/foo' }) + res.ok({ body: 'value:/foo' }) ); const { registerRouter, server: innerServer } = await server.setup(configWithBasePath); @@ -428,7 +429,7 @@ describe('with `basepath: /bar` and `rewriteBasePath: false`', () => { .get('/') .expect(200) .then(res => { - expect(res.body).toEqual({ key: 'value:/' }); + expect(res.text).toBe('value:/'); }); }); @@ -437,7 +438,7 @@ describe('with `basepath: /bar` and `rewriteBasePath: false`', () => { .get('/foo') .expect(200) .then(res => { - expect(res.body).toEqual({ key: 'value:/foo' }); + expect(res.text).toBe('value:/foo'); }); }); }); @@ -453,10 +454,10 @@ describe('with `basepath: /bar` and `rewriteBasePath: true`', () => { rewriteBasePath: true, } as HttpConfig; - const router = new Router('/', logger); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ key: 'value:/' })); + const router = new Router('/', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: 'value:/' })); router.get({ path: '/foo', validate: false }, (context, req, res) => - res.ok({ key: 'value:/foo' }) + res.ok({ body: 'value:/foo' }) ); const { registerRouter, server: innerServer } = await server.setup(configWithBasePath); @@ -471,7 +472,7 @@ describe('with `basepath: /bar` and `rewriteBasePath: true`', () => { .get('/bar') .expect(200) .then(res => { - expect(res.body).toEqual({ key: 'value:/' }); + expect(res.text).toBe('value:/'); }); }); @@ -480,7 +481,7 @@ describe('with `basepath: /bar` and `rewriteBasePath: true`', () => { .get('/bar/') .expect(200) .then(res => { - expect(res.body).toEqual({ key: 'value:/' }); + expect(res.text).toBe('value:/'); }); }); @@ -489,7 +490,7 @@ describe('with `basepath: /bar` and `rewriteBasePath: true`', () => { .get('/bar/foo') .expect(200) .then(res => { - expect(res.body).toEqual({ key: 'value:/foo' }); + expect(res.text).toBe('value:/foo'); }); }); @@ -507,8 +508,8 @@ describe('with `basepath: /bar` and `rewriteBasePath: true`', () => { }); test('with defined `redirectHttpFromPort`', async () => { - const router = new Router('/', logger); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ key: 'value:/' })); + const router = new Router('/', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: 'value:/' })); const { registerRouter } = await server.setup(configWithSSL); registerRouter(router); @@ -537,12 +538,12 @@ test('allows attaching metadata to attach meta-data tag strings to a route', asy const tags = ['my:tag']; const { registerRouter, server: innerServer } = await server.setup(config); - const router = new Router('', logger); + const router = new Router('', logger, enhanceWithContext); router.get({ path: '/with-tags', validate: false, options: { tags } }, (context, req, res) => - res.ok({ tags: req.route.options.tags }) + res.ok({ body: { tags: req.route.options.tags } }) ); router.get({ path: '/without-tags', validate: false }, (context, req, res) => - res.ok({ tags: req.route.options.tags }) + res.ok({ body: { tags: req.route.options.tags } }) ); registerRouter(router); @@ -559,8 +560,8 @@ test('allows attaching metadata to attach meta-data tag strings to a route', asy test('exposes route details of incoming request to a route handler', async () => { const { registerRouter, server: innerServer } = await server.setup(config); - const router = new Router('', logger); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok(req.route)); + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: req.route })); registerRouter(router); await server.start(); @@ -599,9 +600,9 @@ describe('setup contract', () => { config ); - const router = new Router('', logger); + const router = new Router('', logger, enhanceWithContext); router.get({ path: '/', validate: false }, (context, req, res) => - res.ok({ isAuthenticated: auth.isAuthenticated(req) }) + res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) ); registerRouter(router); @@ -618,10 +619,10 @@ describe('setup contract', () => { config ); - const router = new Router('', logger); + const router = new Router('', logger, enhanceWithContext); router.get( { path: '/', validate: false, options: { authRequired: false } }, - (context, req, res) => res.ok({ isAuthenticated: auth.isAuthenticated(req) }) + (context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) ); registerRouter(router); @@ -636,10 +637,10 @@ describe('setup contract', () => { it('returns false if no authorization mechanism has been registered', async () => { const { registerRouter, server: innerServer, auth } = await server.setup(config); - const router = new Router('', logger); + const router = new Router('', logger, enhanceWithContext); router.get( { path: '/', validate: false, options: { authRequired: false } }, - (context, req, res) => res.ok({ isAuthenticated: auth.isAuthenticated(req) }) + (context, req, res) => res.ok({ body: { isAuthenticated: auth.isAuthenticated(req) } }) ); registerRouter(router); @@ -666,8 +667,10 @@ describe('setup contract', () => { return toolkit.authenticated({ state: user }); }); - const router = new Router('', logger); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok(auth.get(req))); + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => + res.ok({ body: auth.get(req) }) + ); registerRouter(router); await server.start(); @@ -678,8 +681,11 @@ describe('setup contract', () => { it('returns correct authentication unknown status', async () => { const { registerRouter, server: innerServer, auth } = await server.setup(config); - const router = new Router('', logger); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok(auth.get(req))); + + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => + res.ok({ body: auth.get(req) }) + ); registerRouter(router); await server.start(); @@ -695,10 +701,10 @@ describe('setup contract', () => { config ); await registerAuth(authenticate); - const router = new Router('', logger); + const router = new Router('', logger, enhanceWithContext); router.get( { path: '/', validate: false, options: { authRequired: false } }, - (context, req, res) => res.ok(auth.get(req)) + (context, req, res) => res.ok({ body: auth.get(req) }) ); registerRouter(router); diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index 41c9afd352116..cb6906379c4ef 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -66,12 +66,13 @@ import { BasePath } from './base_path_service'; * And `response` object instructing HTTP server to create HTTP response with information sent back to the client as the response body, headers, and HTTP status. * Unlike, `hapi` route handler in the Legacy platform, any exception raised during the handler call will generate `500 Server error` response and log error details for further investigation. See below for returning custom error responses. * ```ts - * const handler = async (request: KibanaRequest, response: ResponseFactory) => { + * const handler = async (context: RequestHandlerContext, request: KibanaRequest, response: ResponseFactory) => { * const data = await findObject(request.params.id); * // creates a command to respond with 'not found' error * if (!data) return response.notFound(); * // creates a command to send found data to the client and set response headers - * return response.ok(data, { + * return response.ok({ + * body: data, * headers: { * 'content-type': 'application/json' * } @@ -97,7 +98,8 @@ import { BasePath } from './base_path_service'; * async (context, request, response) => { * const data = await findObject(request.params.id); * if (!data) return response.notFound(); - * return response.ok(data, { + * return response.ok({ + * body: data, * headers: { * 'content-type': 'application/json' * } @@ -289,7 +291,7 @@ export class HttpServer { if (shouldRedirect) { return toolkit.rewriteUrl(newURL); } - return response.notFound(new Error('not found')); + return response.notFound(); }); } diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index ee09e55200853..e834e19fc77d8 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -56,6 +56,7 @@ const createSetupContractMock = () => { registerOnPreAuth: jest.fn(), registerAuth: jest.fn(), registerOnPostAuth: jest.fn(), + registerRouteHandlerContext: jest.fn(), createRouter: jest.fn(), basePath: createBasePathMock(), auth: { @@ -98,4 +99,5 @@ export const httpServiceMock = { createSetupContract: createSetupContractMock, createOnPreAuthToolkit: createOnPreAuthToolkitMock, createAuthToolkit: createAuthToolkitMock, + createRouter: createRouterMock, }; diff --git a/src/core/server/http/http_service.test.ts b/src/core/server/http/http_service.test.ts index d1e906f300d68..eee8094417260 100644 --- a/src/core/server/http/http_service.test.ts +++ b/src/core/server/http/http_service.test.ts @@ -26,6 +26,7 @@ import { HttpConfigType, config } from './http_config'; import { httpServerMock } from './http_server.mocks'; import { Config, ConfigService, Env, ObjectToConfigAdapter } from '../config'; import { loggingServiceMock } from '../logging/logging_service.mock'; +import { contextServiceMock } from '../context/context_service.mock'; import { getEnvOptions } from '../config/__mocks__/env'; const logger = loggingServiceMock.create(); @@ -45,6 +46,11 @@ const createConfigService = (value: Partial = {}) => { configService.setSchema(config.path, config.schema); return configService; }; +const contextSetup = contextServiceMock.createSetupContract(); + +const setupDeps = { + context: contextSetup, +}; const fakeHapiServer = { start: noop, stop: noop, @@ -75,7 +81,7 @@ test('creates and sets up http server', async () => { expect(httpServer.setup).not.toHaveBeenCalled(); - await service.setup(); + await service.setup(setupDeps); expect(httpServer.setup).toHaveBeenCalled(); expect(httpServer.start).not.toHaveBeenCalled(); @@ -110,7 +116,7 @@ test('spins up notReady server until started if configured with `autoListen:true logger, }); - await service.setup(); + await service.setup(setupDeps); const mockResponse: any = { code: jest.fn().mockImplementation(() => mockResponse), @@ -148,7 +154,7 @@ test('logs error if already set up', async () => { const service = new HttpService({ coreId, configService, env, logger }); - await service.setup(); + await service.setup(setupDeps); expect(loggingServiceMock.collect(logger).warn).toMatchSnapshot(); }); @@ -166,7 +172,7 @@ test('stops http server', async () => { const service = new HttpService({ coreId, configService, env, logger }); - await service.setup(); + await service.setup(setupDeps); await service.start(); expect(httpServer.stop).toHaveBeenCalledTimes(0); @@ -193,7 +199,7 @@ test('stops not ready server if it is running', async () => { const service = new HttpService({ coreId, configService, env, logger }); - await service.setup(); + await service.setup(setupDeps); await service.stop(); @@ -216,7 +222,7 @@ test('register route handler', async () => { const service = new HttpService({ coreId, configService, env, logger }); - const { createRouter } = await service.setup(); + const { createRouter } = await service.setup(setupDeps); const router = createRouter('/foo'); expect(registerRouterMock).toHaveBeenCalledTimes(1); @@ -234,7 +240,7 @@ test('returns http server contract on setup', async () => { })); const service = new HttpService({ coreId, configService, env, logger }); - const setupContract = await service.setup(); + const setupContract = await service.setup(setupDeps); expect(setupContract).toMatchObject(httpServer); expect(setupContract).toMatchObject({ createRouter: expect.any(Function), @@ -258,7 +264,7 @@ test('does not start http server if process is dev cluster master', async () => logger, }); - await service.setup(); + await service.setup(setupDeps); await service.start(); expect(httpServer.start).not.toHaveBeenCalled(); @@ -283,7 +289,7 @@ test('does not start http server if configured with `autoListen:false`', async ( logger, }); - await service.setup(); + await service.setup(setupDeps); await service.start(); expect(httpServer.start).not.toHaveBeenCalled(); diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts index 211b11612de12..5814991a2dd27 100644 --- a/src/core/server/http/http_service.ts +++ b/src/core/server/http/http_service.ts @@ -25,13 +25,23 @@ import { LoggerFactory } from '../logging'; import { CoreService } from '../../types'; import { Logger } from '../logging'; +import { ContextSetup } from '../context'; import { CoreContext } from '../core_context'; +import { PluginOpaqueId } from '../plugins'; import { Router, IRouter } from './router'; import { HttpConfig, HttpConfigType } from './http_config'; import { HttpServer, HttpServerSetup } from './http_server'; import { HttpsRedirectServer } from './https_redirect_server'; +import { RequestHandlerContextContainer, RequestHandlerContextProvider } from './types'; + +import { RequestHandlerContext } from '../../server'; + +interface SetupDeps { + context: ContextSetup; +} + /** @public */ export type HttpServiceSetup = Omit & { /** @@ -44,10 +54,37 @@ export type HttpServiceSetup = Omit & { * // handler is called when '${my-plugin-id}/path' resource is requested with `GET` method * router.get({ path: '/path', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); * ``` + * @public + */ + createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter; + /** + * Register a context provider for a route handler. + * @example + * ```ts + * // my-plugin.ts + * deps.http.registerRouteHandlerContext( + * 'myApp', + * (context, req) => { + * async function search (id: string) { + * return await context.elasticsearch.adminClient.callAsInternalUser('endpoint', id); + * } + * return { search }; + * } + * ); * - * @internal - * */ - createRouter: (path: string) => IRouter; + * // my-route-handler.ts + * router.get({ path: '/', validate: false }, async (context, req, res) => { + * const response = await context.myApp.search(...); + * return res.ok(response); + * }); + * ``` + * @public + */ + registerRouteHandlerContext: ( + pluginOpaqueId: PluginOpaqueId, + contextName: T, + provider: RequestHandlerContextProvider + ) => RequestHandlerContextContainer; }; /** @public */ @@ -66,6 +103,7 @@ export class HttpService implements CoreService; constructor(private readonly coreContext: CoreContext) { this.logger = coreContext.logger; @@ -80,7 +118,8 @@ export class HttpService implements CoreService { if (this.httpServer.isListening()) { // If the server is already running we can't make any config changes @@ -101,11 +140,18 @@ export class HttpService implements CoreService { - const router = new Router(path, this.log); + createRouter: (path: string, pluginId: PluginOpaqueId = this.coreContext.coreId) => { + const enhanceHandler = this.requestHandlerContext!.createHandler.bind(null, pluginId); + const router = new Router(path, this.log, enhanceHandler); registerRouter(router); return router; }, + + registerRouteHandlerContext: ( + pluginOpaqueId: PluginOpaqueId, + contextName: T, + provider: RequestHandlerContextProvider + ) => this.requestHandlerContext!.registerContext(pluginOpaqueId, contextName, provider), }; return contract; diff --git a/src/core/server/http/http_tools.test.ts b/src/core/server/http/http_tools.test.ts index 7cda25d957b42..bed0ac8d77094 100644 --- a/src/core/server/http/http_tools.test.ts +++ b/src/core/server/http/http_tools.test.ts @@ -17,16 +17,22 @@ * under the License. */ +jest.mock('fs', () => ({ + readFileSync: jest.fn(), +})); + import supertest from 'supertest'; import { Request, ResponseToolkit } from 'hapi'; import Joi from 'joi'; -import { defaultValidationErrorHandler, HapiValidationError } from './http_tools'; +import { defaultValidationErrorHandler, HapiValidationError, getServerOptions } from './http_tools'; import { HttpServer } from './http_server'; -import { HttpConfig } from './http_config'; +import { HttpConfig, config } from './http_config'; import { Router } from './router'; import { loggingServiceMock } from '../logging/logging_service.mock'; import { ByteSizeValue } from '@kbn/config-schema'; +import { Env } from '../config'; +import { getEnvOptions } from '../config/__mocks__/env'; const emptyOutput = { statusCode: 400, @@ -41,6 +47,8 @@ const emptyOutput = { }, }; +afterEach(() => jest.clearAllMocks()); + describe('defaultValidationErrorHandler', () => { it('formats value validation errors correctly', () => { expect.assertions(1); @@ -68,9 +76,10 @@ describe('defaultValidationErrorHandler', () => { describe('timeouts', () => { const logger = loggingServiceMock.create(); const server = new HttpServer(logger, 'foo'); + const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {}); test('closes sockets on timeout', async () => { - const router = new Router('', logger.get()); + const router = new Router('', logger.get(), enhanceWithContext); router.get({ path: '/a', validate: false }, async (context, req, res) => { await new Promise(resolve => setTimeout(resolve, 2000)); return res.ok({}); @@ -97,3 +106,68 @@ describe('timeouts', () => { await server.stop(); }); }); + +describe('getServerOptions', () => { + beforeEach(() => + jest.requireMock('fs').readFileSync.mockImplementation((path: string) => `content-${path}`) + ); + + it('properly configures TLS with default options', () => { + const httpConfig = new HttpConfig( + config.schema.validate({ + ssl: { + enabled: true, + key: 'some-key-path', + certificate: 'some-certificate-path', + }, + }), + Env.createDefault(getEnvOptions()) + ); + + expect(getServerOptions(httpConfig).tls).toMatchInlineSnapshot(` + Object { + "ca": undefined, + "cert": "content-some-certificate-path", + "ciphers": "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", + "honorCipherOrder": true, + "key": "content-some-key-path", + "passphrase": undefined, + "rejectUnauthorized": false, + "requestCert": false, + "secureOptions": 67108864, + } + `); + }); + + it('properly configures TLS with client authentication', () => { + const httpConfig = new HttpConfig( + config.schema.validate({ + ssl: { + enabled: true, + key: 'some-key-path', + certificate: 'some-certificate-path', + certificateAuthorities: ['ca-1', 'ca-2'], + clientAuthentication: 'required', + }, + }), + Env.createDefault(getEnvOptions()) + ); + + expect(getServerOptions(httpConfig).tls).toMatchInlineSnapshot(` + Object { + "ca": Array [ + "content-ca-1", + "content-ca-2", + ], + "cert": "content-some-certificate-path", + "ciphers": "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", + "honorCipherOrder": true, + "key": "content-some-key-path", + "passphrase": undefined, + "rejectUnauthorized": true, + "requestCert": true, + "secureOptions": 67108864, + } + `); + }); +}); diff --git a/src/core/server/http/http_tools.ts b/src/core/server/http/http_tools.ts index 2953d5272ebe9..88164a76c66f0 100644 --- a/src/core/server/http/http_tools.ts +++ b/src/core/server/http/http_tools.ts @@ -71,6 +71,7 @@ export function getServerOptions(config: HttpConfig, { configureTLS = true } = { passphrase: ssl.keyPassphrase, secureOptions: ssl.getSecureOptions(), requestCert: ssl.requestCert, + rejectUnauthorized: ssl.rejectUnauthorized, }; options.tls = tlsOptions; diff --git a/src/core/server/http/index.ts b/src/core/server/http/index.ts index 8f4ada40733ce..895396b91eb46 100644 --- a/src/core/server/http/index.ts +++ b/src/core/server/http/index.ts @@ -28,6 +28,7 @@ export { isRealRequest, HttpResponseOptions, HttpResponsePayload, + ErrorHttpResponseOptions, KibanaRequest, KibanaRequestRoute, KnownHeaders, @@ -36,7 +37,8 @@ export { RedirectResponseOptions, RequestHandler, ResponseError, - ResponseErrorMeta, + ResponseErrorAttributes, + ResponseHeaders, kibanaResponseFactory, KibanaResponseFactory, RouteConfig, @@ -55,3 +57,4 @@ export { export { OnPostAuthHandler, OnPostAuthToolkit } from './lifecycle/on_post_auth'; export { SessionStorageFactory, SessionStorage } from './session_storage'; export { SessionStorageCookieOptions } from './cookie_session_storage'; +export * from './types'; diff --git a/src/core/server/http/integration_tests/core_services.test.ts b/src/core/server/http/integration_tests/core_services.test.ts index d5f7e262c418a..8a096d4d44371 100644 --- a/src/core/server/http/integration_tests/core_services.test.ts +++ b/src/core/server/http/integration_tests/core_services.test.ts @@ -18,7 +18,6 @@ */ import Boom from 'boom'; import { Request } from 'hapi'; -import { first } from 'rxjs/operators'; import { clusterClientMock } from './core_service.test.mocks'; import * as kbnTestServer from '../../../../test_utils/kbn_server'; @@ -250,9 +249,10 @@ describe('http service', () => { clusterClientMock.mockClear(); await root.shutdown(); }); + it('rewrites authorization header via authHeaders to make a request to Elasticsearch', async () => { const authHeaders = { authorization: 'Basic: user:password' }; - const { http, elasticsearch } = await root.setup(); + const { http } = await root.setup(); const { registerAuth, createRouter } = http; await registerAuth((req, res, toolkit) => @@ -260,32 +260,30 @@ describe('http service', () => { ); const router = createRouter('/new-platform'); - router.get({ path: '/', validate: false }, async (context, req, res) => { - const client = await elasticsearch.dataClient$.pipe(first()).toPromise(); - client.asScoped(req); - return res.ok({ header: 'ok' }); - }); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); await root.start(); await kbnTestServer.request.get(root, '/new-platform/').expect(200); - expect(clusterClientMock).toBeCalledTimes(1); - const [firstCall] = clusterClientMock.mock.calls; - const [, , headers] = firstCall; - expect(headers).toEqual(authHeaders); + + // called twice by elasticsearch service in http route handler context provider + expect(clusterClientMock).toBeCalledTimes(2); + + // admin client contains authHeaders for BWC with legacy platform. + const [adminClient, dataClient] = clusterClientMock.mock.calls; + const [, , adminClientHeaders] = adminClient; + expect(adminClientHeaders).toEqual(authHeaders); + const [, , dataClientHeaders] = dataClient; + expect(dataClientHeaders).toEqual(authHeaders); }); it('passes request authorization header to Elasticsearch if registerAuth was not set', async () => { const authorizationHeader = 'Basic: username:password'; - const { http, elasticsearch } = await root.setup(); + const { http } = await root.setup(); const { createRouter } = http; const router = createRouter('/new-platform'); - router.get({ path: '/', validate: false }, async (context, req, res) => { - const client = await elasticsearch.dataClient$.pipe(first()).toPromise(); - client.asScoped(req); - return res.ok({ header: 'ok' }); - }); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); await root.start(); @@ -294,12 +292,14 @@ describe('http service', () => { .set('Authorization', authorizationHeader) .expect(200); - expect(clusterClientMock).toBeCalledTimes(1); - const [firstCall] = clusterClientMock.mock.calls; - const [, , headers] = firstCall; - expect(headers).toEqual({ - authorization: authorizationHeader, - }); + // called twice by elasticsearch service in http route handler context provider + expect(clusterClientMock).toBeCalledTimes(2); + + const [adminClient, dataClient] = clusterClientMock.mock.calls; + const [, , adminClientHeaders] = adminClient; + expect(adminClientHeaders).toEqual({ authorization: authorizationHeader }); + const [, , dataClientHeaders] = dataClient; + expect(dataClientHeaders).toEqual({ authorization: authorizationHeader }); }); }); }); diff --git a/src/core/server/http/integration_tests/lifecycle.test.ts b/src/core/server/http/integration_tests/lifecycle.test.ts index cbc7cff46186c..4592a646b7f04 100644 --- a/src/core/server/http/integration_tests/lifecycle.test.ts +++ b/src/core/server/http/integration_tests/lifecycle.test.ts @@ -29,6 +29,7 @@ import { CoreContext } from '../../core_context'; import { Env } from '../../config'; import { getEnvOptions } from '../../config/__mocks__/env'; import { configServiceMock } from '../../config/config_service.mock'; +import { contextServiceMock } from '../../context/context_service.mock'; import { loggingServiceMock } from '../../logging/logging_service.mock'; let server: HttpService; @@ -37,7 +38,11 @@ let logger: ReturnType; let env: Env; let coreContext: CoreContext; const configService = configServiceMock.create(); +const contextSetup = contextServiceMock.createSetupContract(); +const setupDeps = { + context: contextSetup, +}; configService.atPath.mockReturnValue( new BehaviorSubject({ hosts: ['localhost'], @@ -73,10 +78,10 @@ interface StorageData { describe('OnPreAuth', () => { it('supports registering request inceptors', async () => { - const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok('ok')); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: 'ok' })); const callingOrder: string[] = []; registerOnPreAuth((req, res, t) => { @@ -98,12 +103,14 @@ describe('OnPreAuth', () => { }); it('supports request forwarding to specified url', async () => { - const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/initial', validate: false }, (context, req, res) => res.ok('initial')); + router.get({ path: '/initial', validate: false }, (context, req, res) => + res.ok({ body: 'initial' }) + ); router.get({ path: '/redirectUrl', validate: false }, (context, req, res) => - res.ok('redirected') + res.ok({ body: 'redirected' }) ); let urlBeforeForwarding; @@ -130,14 +137,14 @@ describe('OnPreAuth', () => { }); it('supports redirection from the interceptor', async () => { - const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); const redirectUrl = '/redirectUrl'; - router.get({ path: '/initial', validate: false }, (context, req, res) => res.ok('initial')); + router.get({ path: '/initial', validate: false }, (context, req, res) => res.ok()); registerOnPreAuth((req, res, t) => - res.redirected(undefined, { + res.redirected({ headers: { location: redirectUrl, }, @@ -153,13 +160,13 @@ describe('OnPreAuth', () => { }); it('supports rejecting request and adjusting response headers', async () => { - const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok(undefined)); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); registerOnPreAuth((req, res, t) => - res.unauthorized('not found error', { + res.unauthorized({ headers: { 'www-authenticate': 'challenge', }, @@ -175,10 +182,10 @@ describe('OnPreAuth', () => { }); it("doesn't expose error details if interceptor throws", async () => { - const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok(undefined)); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); registerOnPreAuth((req, res, t) => { throw new Error('reason'); @@ -200,10 +207,10 @@ describe('OnPreAuth', () => { }); it('returns internal error if interceptor returns unexpected result', async () => { - const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok('ok')); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); registerOnPreAuth((req, res, t) => ({} as any)); await server.start(); @@ -223,7 +230,7 @@ describe('OnPreAuth', () => { }); it(`doesn't share request object between interceptors`, async () => { - const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPreAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); registerOnPreAuth((req, res, t) => { @@ -240,7 +247,7 @@ describe('OnPreAuth', () => { }); router.get({ path: '/', validate: false }, (context, req, res) => // don't complain customField is not defined on Request type - res.ok({ customField: String((req as any).customField) }) + res.ok({ body: { customField: String((req as any).customField) } }) ); await server.start(); @@ -253,10 +260,10 @@ describe('OnPreAuth', () => { describe('OnPostAuth', () => { it('supports registering request inceptors', async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok('ok')); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ body: 'ok' })); const callingOrder: string[] = []; registerOnPostAuth((req, res, t) => { @@ -278,14 +285,14 @@ describe('OnPostAuth', () => { }); it('supports redirection from the interceptor', async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); const redirectUrl = '/redirectUrl'; - router.get({ path: '/initial', validate: false }, (context, req, res) => res.ok('initial')); + router.get({ path: '/initial', validate: false }, (context, req, res) => res.ok()); registerOnPostAuth((req, res, t) => - res.redirected(undefined, { + res.redirected({ headers: { location: redirectUrl, }, @@ -301,12 +308,12 @@ describe('OnPostAuth', () => { }); it('supports rejecting request and adjusting response headers', async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => res.ok(undefined)); registerOnPostAuth((req, res, t) => - res.unauthorized('not found error', { + res.unauthorized({ headers: { 'www-authenticate': 'challenge', }, @@ -322,7 +329,7 @@ describe('OnPostAuth', () => { }); it("doesn't expose error details if interceptor throws", async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => res.ok(undefined)); @@ -346,10 +353,10 @@ describe('OnPostAuth', () => { }); it('returns internal error if interceptor returns unexpected result', async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok('ok')); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); registerOnPostAuth((req, res, t) => ({} as any)); await server.start(); @@ -368,7 +375,7 @@ describe('OnPostAuth', () => { }); it(`doesn't share request object between interceptors`, async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); registerOnPostAuth((req, res, t) => { @@ -386,7 +393,7 @@ describe('OnPostAuth', () => { router.get({ path: '/', validate: false }, (context, req, res) => // don't complain customField is not defined on Request type - res.ok({ customField: String((req as any).customField) }) + res.ok({ body: { customField: String((req as any).customField) } }) ); await server.start(); @@ -406,7 +413,7 @@ describe('Auth', () => { }; it('registers auth request interceptor only once', async () => { - const { registerAuth } = await server.setup(); + const { registerAuth } = await server.setup(setupDeps); const doRegister = () => registerAuth(() => null as any); doRegister(); @@ -414,10 +421,12 @@ describe('Auth', () => { }); it('may grant access to a resource', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + router.get({ path: '/', validate: false }, (context, req, res) => + res.ok({ body: { content: 'ok' } }) + ); registerAuth((req, res, t) => t.authenticated()); await server.start(); @@ -427,11 +436,11 @@ describe('Auth', () => { }); it('enables auth for a route by default if registerAuth has been called', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => - res.ok({ authRequired: req.route.options.authRequired }) + res.ok({ body: { authRequired: req.route.options.authRequired } }) ); const authenticate = jest.fn().mockImplementation((req, res, t) => t.authenticated()); registerAuth(authenticate); @@ -445,12 +454,12 @@ describe('Auth', () => { }); test('supports disabling auth for a route explicitly', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get( { path: '/', validate: false, options: { authRequired: false } }, - (context, req, res) => res.ok({ authRequired: req.route.options.authRequired }) + (context, req, res) => res.ok({ body: { authRequired: req.route.options.authRequired } }) ); const authenticate = jest.fn(); @@ -465,12 +474,12 @@ describe('Auth', () => { }); test('supports enabling auth for a route explicitly', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get( { path: '/', validate: false, options: { authRequired: true } }, - (context, req, res) => res.ok({ authRequired: req.route.options.authRequired }) + (context, req, res) => res.ok({ body: { authRequired: req.route.options.authRequired } }) ); const authenticate = jest.fn().mockImplementation((req, res, t) => t.authenticated({})); @@ -485,10 +494,10 @@ describe('Auth', () => { }); it('supports rejecting a request from an unauthenticated user', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); registerAuth((req, res) => res.unauthorized()); await server.start(); @@ -498,13 +507,13 @@ describe('Auth', () => { }); it('supports redirecting', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); const redirectTo = '/redirect-url'; registerAuth((req, res) => - res.redirected(undefined, { + res.redirected({ headers: { location: redirectTo, }, @@ -519,10 +528,10 @@ describe('Auth', () => { }); it(`doesn't expose internal error details`, async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); registerAuth((req, t) => { throw new Error('reason'); }); @@ -548,10 +557,10 @@ describe('Auth', () => { registerAuth, server: innerServer, createRouter, - } = await server.setup(); + } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); const sessionStorageFactory = await createCookieSessionStorageFactory( cookieOptions @@ -567,7 +576,7 @@ describe('Auth', () => { const response = await supertest(innerServer.listener) .get('/') - .expect(200, { content: 'ok' }); + .expect(200); expect(response.header['set-cookie']).toBeDefined(); const cookies = response.header['set-cookie']; @@ -590,7 +599,7 @@ describe('Auth', () => { registerAuth, server: innerServer, createRouter, - } = await server.setup(); + } = await server.setup(setupDeps); const router = createRouter('/'); const sessionStorageFactory = await createCookieSessionStorageFactory( @@ -603,11 +612,11 @@ describe('Auth', () => { return toolkit.authenticated(); }); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ content: 'ok' })); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); router.get({ path: '/with-cookie', validate: false }, (context, req, res) => { const sessionStorage = sessionStorageFactory.asScoped(req); sessionStorage.clear(); - return res.ok({ content: 'ok' }); + return res.ok(); }); await server.start(); @@ -633,7 +642,7 @@ describe('Auth', () => { registerOnPostAuth, server: innerServer, createRouter, - } = await server.setup(); + } = await server.setup(setupDeps); const router = createRouter('/'); let fromRegisterOnPreAuth; @@ -658,7 +667,7 @@ describe('Auth', () => { router.get({ path: '/', validate: false }, (context, req, res) => { fromRouteHandler = req.headers.authorization; - return res.ok({ content: 'ok' }); + return res.ok(); }); await server.start(); @@ -675,7 +684,7 @@ describe('Auth', () => { }); it('attach security header to a successful response', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); const authResponseHeader = { @@ -685,7 +694,7 @@ describe('Auth', () => { return toolkit.authenticated({ responseHeaders: authResponseHeader }); }); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok({ header: 'ok' })); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); await server.start(); const response = await supertest(innerServer.listener) @@ -696,7 +705,7 @@ describe('Auth', () => { }); it('attach security header to an error response', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); const authResponseHeader = { 'www-authenticate': 'Negotiate ade0234568a4209af8bc0280289eca', @@ -706,9 +715,7 @@ describe('Auth', () => { return toolkit.authenticated({ responseHeaders: authResponseHeader }); }); - router.get({ path: '/', validate: false }, (context, req, res) => - res.badRequest(new Error('reason')) - ); + router.get({ path: '/', validate: false }, (context, req, res) => res.badRequest()); await server.start(); const response = await supertest(innerServer.listener) @@ -719,7 +726,7 @@ describe('Auth', () => { }); it('logs warning if Auth Security Header rewrites response header for success response', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); const authResponseHeader = { @@ -731,14 +738,11 @@ describe('Auth', () => { }); router.get({ path: '/', validate: false }, (context, req, res) => - res.ok( - {}, - { - headers: { - 'www-authenticate': 'from handler', - }, - } - ) + res.ok({ + headers: { + 'www-authenticate': 'from handler', + }, + }) ); await server.start(); @@ -757,7 +761,7 @@ describe('Auth', () => { }); it('logs warning if Auth Security Header rewrites response header for error response', async () => { - const { registerAuth, server: innerServer, createRouter } = await server.setup(); + const { registerAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); const authResponseHeader = { @@ -769,7 +773,7 @@ describe('Auth', () => { }); router.get({ path: '/', validate: false }, (context, req, res) => - res.badRequest('reason', { + res.badRequest({ headers: { 'www-authenticate': 'from handler', }, @@ -792,13 +796,13 @@ describe('Auth', () => { }); it('supports redirection from the interceptor', async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); const redirectUrl = '/redirectUrl'; - router.get({ path: '/initial', validate: false }, (context, req, res) => res.ok('initial')); + router.get({ path: '/initial', validate: false }, (context, req, res) => res.ok()); registerOnPostAuth((req, res, t) => - res.redirected(undefined, { + res.redirected({ headers: { location: redirectUrl, }, @@ -814,13 +818,13 @@ describe('Auth', () => { }); it('supports rejecting request and adjusting response headers', async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => res.ok(undefined)); registerOnPostAuth((req, res, t) => - res.unauthorized('not found error', { + res.unauthorized({ headers: { 'www-authenticate': 'challenge', }, @@ -836,7 +840,7 @@ describe('Auth', () => { }); it("doesn't expose error details if interceptor throws", async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => res.ok(undefined)); @@ -860,10 +864,10 @@ describe('Auth', () => { }); it('returns internal error if interceptor returns unexpected result', async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); - router.get({ path: '/', validate: false }, (context, req, res) => res.ok('ok')); + router.get({ path: '/', validate: false }, (context, req, res) => res.ok()); registerOnPostAuth((req, res, t) => ({} as any)); await server.start(); @@ -882,7 +886,7 @@ describe('Auth', () => { }); // eslint-disable-next-line it(`doesn't share request object between interceptors`, async () => { - const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(); + const { registerOnPostAuth, server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); registerOnPostAuth((req, res, t) => { @@ -899,7 +903,7 @@ describe('Auth', () => { }); router.get({ path: '/', validate: false }, (context, req, res) => // don't complain customField is not defined on Request type - res.ok({ customField: String((req as any).customField) }) + res.ok({ body: { customField: String((req as any).customField) } }) ); await server.start(); diff --git a/src/core/server/http/integration_tests/router.test.ts b/src/core/server/http/integration_tests/router.test.ts index 49beae161b9a3..70d7ae00f917e 100644 --- a/src/core/server/http/integration_tests/router.test.ts +++ b/src/core/server/http/integration_tests/router.test.ts @@ -29,6 +29,7 @@ import { CoreContext } from '../../core_context'; import { Env } from '../../config'; import { getEnvOptions } from '../../config/__mocks__/env'; import { configServiceMock } from '../../config/config_service.mock'; +import { contextServiceMock } from '../../context/context_service.mock'; import { loggingServiceMock } from '../../logging/logging_service.mock'; let server: HttpService; @@ -37,7 +38,11 @@ let logger: ReturnType; let env: Env; let coreContext: CoreContext; const configService = configServiceMock.create(); +const contextSetup = contextServiceMock.createSetupContract(); +const setupDeps = { + context: contextSetup, +}; configService.atPath.mockReturnValue( new BehaviorSubject({ hosts: ['localhost'], @@ -63,7 +68,7 @@ afterEach(async () => { describe('Handler', () => { it("Doesn't expose error details if handler throws", async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -86,7 +91,7 @@ describe('Handler', () => { }); it('returns 500 Server error if handler throws Boom error', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -109,7 +114,7 @@ describe('Handler', () => { }); it('returns 500 Server error if handler returns unexpected result', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => 'ok' as any); @@ -130,7 +135,7 @@ describe('Handler', () => { }); it('returns 400 Bad request if request validation failed', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get( @@ -162,11 +167,11 @@ describe('Handler', () => { describe('Response factory', () => { describe('Success', () => { it('supports answering with json object', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.ok({ key: 'value' }); + return res.ok({ body: { key: 'value' } }); }); await server.start(); @@ -180,11 +185,11 @@ describe('Response factory', () => { }); it('supports answering with string', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.ok('result'); + return res.ok({ body: 'result' }); }); await server.start(); @@ -198,7 +203,7 @@ describe('Response factory', () => { }); it('supports answering with undefined', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -213,7 +218,7 @@ describe('Response factory', () => { }); it('supports answering with Stream', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -226,7 +231,7 @@ describe('Response factory', () => { }, }); - return res.ok(stream); + return res.ok({ body: stream }); }); await server.start(); @@ -240,7 +245,7 @@ describe('Response factory', () => { }); it('supports answering with chunked Stream', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -252,7 +257,7 @@ describe('Response factory', () => { stream.end(); }, 100); - return res.ok(stream); + return res.ok({ body: stream }); }); await server.start(); @@ -266,13 +271,14 @@ describe('Response factory', () => { }); it('supports answering with Buffer', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const buffer = Buffer.alloc(1028, '.'); - return res.ok(buffer, { + return res.ok({ + body: buffer, headers: { 'content-encoding': 'binary', }, @@ -292,13 +298,14 @@ describe('Response factory', () => { }); it('supports answering with Buffer text', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const buffer = new Buffer('abc'); - return res.ok(buffer, { + return res.ok({ + body: buffer, headers: { 'content-type': 'text/plain', }, @@ -318,11 +325,12 @@ describe('Response factory', () => { }); it('supports configuring standard headers', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.ok('value', { + return res.ok({ + body: 'value', headers: { etag: '1234', }, @@ -340,11 +348,12 @@ describe('Response factory', () => { }); it('supports configuring non-standard headers', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.ok('value', { + return res.ok({ + body: 'value', headers: { etag: '1234', 'x-kibana': 'key', @@ -364,11 +373,12 @@ describe('Response factory', () => { }); it('accepted headers are case-insensitive.', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.ok('value', { + return res.ok({ + body: 'value', headers: { ETag: '1234', }, @@ -385,11 +395,12 @@ describe('Response factory', () => { }); it('accept array of headers', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.ok('value', { + return res.ok({ + body: 'value', headers: { 'set-cookie': ['foo', 'bar'], }, @@ -406,13 +417,13 @@ describe('Response factory', () => { }); it('throws if given invalid json object as response payload', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const payload: any = { key: {} }; payload.key.payload = payload; - return res.ok(payload); + return res.ok({ body: payload }); }); await server.start(); @@ -426,11 +437,11 @@ describe('Response factory', () => { }); it('200 OK with body', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.ok({ key: 'value' }); + return res.ok({ body: { key: 'value' } }); }); await server.start(); @@ -444,11 +455,11 @@ describe('Response factory', () => { }); it('202 Accepted with body', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.accepted({ location: 'somewhere' }); + return res.accepted({ body: { location: 'somewhere' } }); }); await server.start(); @@ -462,7 +473,7 @@ describe('Response factory', () => { }); it('204 No content', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -481,11 +492,12 @@ describe('Response factory', () => { describe('Redirection', () => { it('302 supports redirection to configured URL', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.redirected('The document has moved', { + return res.redirected({ + body: 'The document has moved', headers: { location: '/new-url', 'x-kibana': 'tag', @@ -505,11 +517,11 @@ describe('Response factory', () => { }); it('throws if redirection url not provided', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.redirected(undefined, { + return res.redirected({ headers: { 'x-kibana': 'tag', }, @@ -535,12 +547,12 @@ describe('Response factory', () => { describe('Error', () => { it('400 Bad request', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('some message'); - return res.badRequest(error); + return res.badRequest({ body: error }); }); await server.start(); @@ -557,7 +569,7 @@ describe('Response factory', () => { }); it('400 Bad request with default message', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -578,11 +590,13 @@ describe('Response factory', () => { }); it('400 Bad request with additional data', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.badRequest({ message: 'some message', meta: { data: ['good', 'bad'] } }); + return res.badRequest({ + body: { message: 'some message', attributes: { data: ['good', 'bad'] } }, + }); }); await server.start(); @@ -594,7 +608,7 @@ describe('Response factory', () => { expect(result.body).toEqual({ error: 'Bad Request', message: 'some message', - meta: { + attributes: { data: ['good', 'bad'], }, statusCode: 400, @@ -602,12 +616,13 @@ describe('Response factory', () => { }); it('401 Unauthorized', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('no access'); - return res.unauthorized(error, { + return res.unauthorized({ + body: error, headers: { 'WWW-Authenticate': 'challenge', }, @@ -625,7 +640,7 @@ describe('Response factory', () => { }); it('401 Unauthorized with default message', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -642,12 +657,12 @@ describe('Response factory', () => { }); it('403 Forbidden', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('reason'); - return res.forbidden(error); + return res.forbidden({ body: error }); }); await server.start(); @@ -660,7 +675,7 @@ describe('Response factory', () => { }); it('403 Forbidden with default message', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -677,12 +692,12 @@ describe('Response factory', () => { }); it('404 Not Found', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('file is not found'); - return res.notFound(error); + return res.notFound({ body: error }); }); await server.start(); @@ -695,7 +710,7 @@ describe('Response factory', () => { }); it('404 Not Found with default message', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -712,12 +727,12 @@ describe('Response factory', () => { }); it('409 Conflict', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('stale version'); - return res.conflict(error); + return res.conflict({ body: error }); }); await server.start(); @@ -730,7 +745,7 @@ describe('Response factory', () => { }); it('409 Conflict with default message', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { @@ -747,12 +762,13 @@ describe('Response factory', () => { }); it('Custom error response', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('some message'); - return res.customError(error, { + return res.customError({ + body: error, statusCode: 418, }); }); @@ -771,13 +787,14 @@ describe('Response factory', () => { }); it('Custom error response for server error', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('some message'); - return res.customError(error, { + return res.customError({ + body: error, statusCode: 500, }); }); @@ -796,13 +813,14 @@ describe('Response factory', () => { }); it('Custom error response for Boom server error', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('some message'); - return res.customError(Boom.boomify(error), { + return res.customError({ + body: Boom.boomify(error), statusCode: 500, }); }); @@ -821,12 +839,13 @@ describe('Response factory', () => { }); it('Custom error response requires error status code', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('some message'); - return res.customError(error, { + return res.customError({ + body: error, statusCode: 200, }); }); @@ -854,11 +873,12 @@ describe('Response factory', () => { describe('Custom', () => { it('creates success response', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom(undefined, { + return res.custom({ + body: undefined, statusCode: 201, headers: { location: 'somewhere', @@ -876,11 +896,12 @@ describe('Response factory', () => { }); it('creates redirect response', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom('The document has moved', { + return res.custom({ + body: 'The document has moved', headers: { location: '/new-url', }, @@ -898,11 +919,12 @@ describe('Response factory', () => { }); it('throws if redirects without location header to be set', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom('The document has moved', { + return res.custom({ + body: 'The document has moved', headers: {}, statusCode: 301, }); @@ -924,12 +946,13 @@ describe('Response factory', () => { }); it('creates error response', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('unauthorized'); - return res.custom(error, { + return res.custom({ + body: error, statusCode: 401, }); }); @@ -944,19 +967,17 @@ describe('Response factory', () => { }); it('creates error response with additional data', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom( - { + return res.custom({ + body: { message: 'unauthorized', - meta: { errorCode: 'K401' }, + attributes: { errorCode: 'K401' }, }, - { - statusCode: 401, - } - ); + statusCode: 401, + }); }); await server.start(); @@ -968,25 +989,23 @@ describe('Response factory', () => { expect(result.body).toEqual({ error: 'Unauthorized', message: 'unauthorized', - meta: { errorCode: 'K401' }, + attributes: { errorCode: 'K401' }, statusCode: 401, }); }); it('creates error response with additional data and error object', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom( - { + return res.custom({ + body: { message: new Error('unauthorized'), - meta: { errorCode: 'K401' }, + attributes: { errorCode: 'K401' }, }, - { - statusCode: 401, - } - ); + statusCode: 401, + }); }); await server.start(); @@ -998,18 +1017,19 @@ describe('Response factory', () => { expect(result.body).toEqual({ error: 'Unauthorized', message: 'unauthorized', - meta: { errorCode: 'K401' }, + attributes: { errorCode: 'K401' }, statusCode: 401, }); }); it('creates error response with Boom error', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = Boom.unauthorized(); - return res.custom(error, { + return res.custom({ + body: error, statusCode: 401, }); }); @@ -1024,11 +1044,12 @@ describe('Response factory', () => { }); it("Doesn't log details of created 500 Server error response", async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom('reason', { + return res.custom({ + body: 'reason', statusCode: 500, }); }); @@ -1044,16 +1065,14 @@ describe('Response factory', () => { }); it('throws an error if not valid error is provided', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom( - { error: 'error-message' }, - { - statusCode: 401, - } - ); + return res.custom({ + body: { error: 'error-message' }, + statusCode: 401, + }); }); await server.start(); @@ -1073,13 +1092,13 @@ describe('Response factory', () => { }); it('throws if an error not provided', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { - return res.custom(undefined, { + return res.custom({ statusCode: 401, - }); + } as any); // requires error message }); await server.start(); @@ -1099,12 +1118,12 @@ describe('Response factory', () => { }); it('throws an error if statusCode is not specified', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('error message'); - return res.custom(error, undefined as any); // options.statusCode is required + return res.custom({ body: error } as any); // options.statusCode is required }); await server.start(); @@ -1124,12 +1143,12 @@ describe('Response factory', () => { }); it('throws an error if statusCode is not valid', async () => { - const { server: innerServer, createRouter } = await server.setup(); + const { server: innerServer, createRouter } = await server.setup(setupDeps); const router = createRouter('/'); router.get({ path: '/', validate: false }, (context, req, res) => { const error = new Error('error message'); - return res.custom(error, { statusCode: 20 }); + return res.custom({ body: error, statusCode: 20 }); }); await server.start(); diff --git a/src/core/server/http/router/index.ts b/src/core/server/http/router/index.ts index 8d54d7f25c538..d7393a1b98546 100644 --- a/src/core/server/http/router/index.ts +++ b/src/core/server/http/router/index.ts @@ -32,9 +32,10 @@ export { CustomHttpResponseOptions, HttpResponseOptions, HttpResponsePayload, + ErrorHttpResponseOptions, RedirectResponseOptions, ResponseError, - ResponseErrorMeta, + ResponseErrorAttributes, KibanaResponse, kibanaResponseFactory, KibanaResponseFactory, diff --git a/src/core/server/http/router/response.ts b/src/core/server/http/router/response.ts index cd977e6b754ab..874b494a1676c 100644 --- a/src/core/server/http/router/response.ts +++ b/src/core/server/http/router/response.ts @@ -20,14 +20,10 @@ import { Stream } from 'stream'; import { ResponseHeaders } from './headers'; /** - * Additional metadata to enhance error output or provide error details. + * Additional data to provide error details. * @public */ -export interface ResponseErrorMeta { - data?: Record; - errorCode?: string; - docLink?: string; -} +export type ResponseErrorAttributes = Record; /** * Error message and optional data send to the client in case of error. * @public @@ -37,7 +33,7 @@ export type ResponseError = | Error | { message: string | Error; - meta?: ResponseErrorMeta; + attributes?: ResponseErrorAttributes; }; /** @@ -57,6 +53,8 @@ export class KibanaResponse * @public */ export interface HttpResponseOptions { + /** HTTP message to send to the client */ + body?: HttpResponsePayload; /** HTTP Headers with additional information about response */ headers?: ResponseHeaders; } @@ -71,7 +69,11 @@ export type HttpResponsePayload = undefined | string | Record | Buf * HTTP response parameters for a response with adjustable status code. * @public */ -export interface CustomHttpResponseOptions extends HttpResponseOptions { +export interface CustomHttpResponseOptions { + /** HTTP message to send to the client */ + body?: T; + /** HTTP Headers with additional information about response */ + headers?: ResponseHeaders; statusCode: number; } @@ -85,29 +87,36 @@ export type RedirectResponseOptions = HttpResponseOptions & { }; }; +/** + * HTTP response parameters + * @public + */ +export interface ErrorHttpResponseOptions { + /** HTTP message to send to the client */ + body?: ResponseError; + /** HTTP Headers with additional information about response */ + headers?: ResponseHeaders; +} + const successResponseFactory = { /** * The request has succeeded. * Status code: `200`. - * @param payload - {@link HttpResponsePayload} payload to send to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response body & headers. */ - ok: (payload: HttpResponsePayload, options: HttpResponseOptions = {}) => - new KibanaResponse(200, payload, options), + ok: (options: HttpResponseOptions = {}) => new KibanaResponse(200, options.body, options), /** * The request has been accepted for processing. * Status code: `202`. - * @param payload - {@link HttpResponsePayload} payload to send to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response body & headers. */ - accepted: (payload?: HttpResponsePayload, options: HttpResponseOptions = {}) => - new KibanaResponse(202, payload, options), + accepted: (options: HttpResponseOptions = {}) => new KibanaResponse(202, options.body, options), /** * The server has successfully fulfilled the request and that there is no additional content to send in the response payload body. * Status code: `204`. - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response body & headers. */ noContent: (options: HttpResponseOptions = {}) => new KibanaResponse(204, undefined, options), }; @@ -116,85 +125,78 @@ const redirectionResponseFactory = { /** * Redirect to a different URI. * Status code: `302`. - * @param payload - payload to send to the client - * @param options - {@link RedirectResponseOptions} configures HTTP response parameters. + * @param options - {@link RedirectResponseOptions} configures HTTP response body & headers. * Expects `location` header to be set. */ - redirected: (payload: HttpResponsePayload, options: RedirectResponseOptions) => - new KibanaResponse(302, payload, options), + redirected: (options: RedirectResponseOptions) => new KibanaResponse(302, options.body, options), }; const errorResponseFactory = { /** * The server cannot process the request due to something that is perceived to be a client error. * Status code: `400`. - * @param error - {@link ResponseError} Error object containing message and other error details to pass to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client */ - badRequest: (error: ResponseError = 'Bad Request', options: HttpResponseOptions = {}) => - new KibanaResponse(400, error, options), + badRequest: (options: ErrorHttpResponseOptions = {}) => + new KibanaResponse(400, options.body || 'Bad Request', options), /** * The request cannot be applied because it lacks valid authentication credentials for the target resource. * Status code: `401`. - * @param error - {@link ResponseError} Error object containing message and other error details to pass to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client */ - unauthorized: (error: ResponseError = 'Unauthorized', options: HttpResponseOptions = {}) => - new KibanaResponse(401, error, options), + unauthorized: (options: ErrorHttpResponseOptions = {}) => + new KibanaResponse(401, options.body || 'Unauthorized', options), /** * Server cannot grant access to a resource. * Status code: `403`. - * @param error - {@link ResponseError} Error object containing message and other error details to pass to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client */ - forbidden: (error: ResponseError = 'Forbidden', options: HttpResponseOptions = {}) => - new KibanaResponse(403, error, options), + forbidden: (options: ErrorHttpResponseOptions = {}) => + new KibanaResponse(403, options.body || 'Forbidden', options), /** * Server cannot find a current representation for the target resource. * Status code: `404`. - * @param error - {@link ResponseError} Error object containing message and other error details to pass to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client */ - notFound: (error: ResponseError = 'Not Found', options: HttpResponseOptions = {}) => - new KibanaResponse(404, error, options), + notFound: (options: ErrorHttpResponseOptions = {}) => + new KibanaResponse(404, options.body || 'Not Found', options), /** * The request could not be completed due to a conflict with the current state of the target resource. * Status code: `409`. - * @param error - {@link ResponseError} Error object containing message and other error details to pass to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client */ - conflict: (error: ResponseError = 'Conflict', options: HttpResponseOptions = {}) => - new KibanaResponse(409, error, options), + conflict: (options: ErrorHttpResponseOptions = {}) => + new KibanaResponse(409, options.body || 'Conflict', options), // Server error /** * The server encountered an unexpected condition that prevented it from fulfilling the request. * Status code: `500`. - * @param error - {@link ResponseError} Error object containing message and other error details to pass to the client - * @param options - {@link HttpResponseOptions} configures HTTP response parameters. + * @param options - {@link HttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client */ - internalError: (error: ResponseError = 'Internal Error', options: HttpResponseOptions = {}) => - new KibanaResponse(500, error, options), + internalError: (options: ErrorHttpResponseOptions = {}) => + new KibanaResponse(500, options.body || 'Internal Error', options), /** * Creates an error response with defined status code and payload. - * @param error - {@link ResponseError} Error object containing message and other error details to pass to the client - * @param options - {@link CustomHttpResponseOptions} configures HTTP response parameters. + * @param options - {@link CustomHttpResponseOptions} configures HTTP response headers, error message and other error details to pass to the client */ - customError: (error: ResponseError, options: CustomHttpResponseOptions) => { + customError: (options: CustomHttpResponseOptions) => { if (!options || !options.statusCode) { - throw new Error(`options.statusCode is expected to be set. given options: ${options}`); + throw new Error( + `options.statusCode is expected to be set. given options: ${options && options.statusCode}` + ); } if (options.statusCode < 400 || options.statusCode >= 600) { throw new Error( `Unexpected Http status code. Expected from 400 to 599, but given: ${options.statusCode}` ); } - return new KibanaResponse(options.statusCode, error, options); + return new KibanaResponse(options.statusCode, options.body, options); }, }; /** @@ -209,19 +211,20 @@ const errorResponseFactory = { * - `Stream` send data stream * - `Buffer` send binary stream * ```js - * return response.ok(undefined); - * return response.ok('ack'); - * return response.ok({ id: '1' }); - * return response.ok(Buffer.from(...);); + * return response.ok(); + * return response.ok({ body: 'ack' }); + * return response.ok({ body: { id: '1' } }); + * return response.ok({ body: Buffer.from(...) }); * * const stream = new Stream.PassThrough(); * fs.createReadStream('./file').pipe(stream); - * return res.ok(stream); + * return res.ok({ body: stream }); * ``` * HTTP headers are configurable via response factory parameter `options` {@link HttpResponseOptions}. * * ```js - * return response.ok({ id: '1' }, { + * return response.ok({ + * body: { id: '1' }, * headers: { * 'content-type': 'application/json' * } @@ -229,7 +232,8 @@ const errorResponseFactory = { * ``` * 2. Redirection response. Redirection URL is configures via 'Location' header. * ```js - * return response.redirected('The document has moved', { + * return response.redirected({ + * body: 'The document has moved', * headers: { * location: '/new-url', * }, @@ -238,49 +242,46 @@ const errorResponseFactory = { * 3. Error response. You may pass an error message to the client, where error message can be: * - `string` send message text * - `Error` send the message text of given Error object. - * - `{ message: string | Error, meta: {data: Record, ...} }` - send message text and attach additional error metadata. + * - `{ message: string | Error, attributes: {data: Record, ...} }` - send message text and attach additional error data. * ```js - * return response.unauthorized('User has no access to the requested resource.', { + * return response.unauthorized({ + * body: 'User has no access to the requested resource.', * headers: { * 'WWW-Authenticate': 'challenge', * } * }) * return response.badRequest(); - * return response.badRequest('validation error'); + * return response.badRequest({ body: 'validation error' }); * * try { * // ... * } catch(error){ - * return response.badRequest(error); + * return response.badRequest({ body: error }); * } * * return response.badRequest({ - * message: 'validation error', - * meta: { - * data: { - * requestBody: request.body, - * failedFields: validationResult - * }, - * } + * body:{ + * message: 'validation error', + * attributes: { + * requestBody: request.body, + * failedFields: validationResult + * } + * } * }); * * try { * // ... * } catch(error) { * return response.badRequest({ - * message: error, - * meta: { - * data: { - * requestBody: request.body, - * }, - * } + * body: error * }); * } * * ``` * 4. Custom response. `ResponseFactory` may not cover your use case, so you can use the `custom` function to customize the response. * ```js - * return response.custom('ok', { + * return response.custom({ + * body: 'ok', * statusCode: 201, * headers: { * location: '/created-url' @@ -295,15 +296,18 @@ export const kibanaResponseFactory = { ...errorResponseFactory, /** * Creates a response with defined status code and payload. - * @param payload - {@link HttpResponsePayload} payload to send to the client * @param options - {@link CustomHttpResponseOptions} configures HTTP response parameters. */ - custom: (payload: HttpResponsePayload | ResponseError, options: CustomHttpResponseOptions) => { + custom: ( + options: CustomHttpResponseOptions + ) => { if (!options || !options.statusCode) { - throw new Error(`options.statusCode is expected to be set. given options: ${options}`); + throw new Error( + `options.statusCode is expected to be set. given options: ${options && options.statusCode}` + ); } - const { statusCode: code, ...rest } = options; - return new KibanaResponse(code, payload, rest); + const { statusCode: code, body, ...rest } = options; + return new KibanaResponse(code, body, rest); }, }; diff --git a/src/core/server/http/router/response_adapter.ts b/src/core/server/http/router/response_adapter.ts index 89fdea1d67f67..fe6cb32d21776 100644 --- a/src/core/server/http/router/response_adapter.ts +++ b/src/core/server/http/router/response_adapter.ts @@ -20,13 +20,12 @@ import { ResponseObject as HapiResponseObject, ResponseToolkit as HapiResponseTo import typeDetect from 'type-detect'; import Boom from 'boom'; -import { HttpResponsePayload, KibanaResponse, ResponseError, ResponseErrorMeta } from './response'; - -declare module 'boom' { - interface Payload { - meta?: ResponseErrorMeta; - } -} +import { + HttpResponsePayload, + KibanaResponse, + ResponseError, + ResponseErrorAttributes, +} from './response'; function setHeaders(response: HapiResponseObject, headers: Record = {}) { Object.entries(headers).forEach(([header, value]) => { @@ -121,7 +120,7 @@ export class HapiResponseAdapter { }); error.output.payload.message = getErrorMessage(payload); - error.output.payload.meta = getErrorMeta(payload); + error.output.payload.attributes = getErrorAttributes(payload); const headers = kibanaResponse.options.headers; if (headers) { @@ -141,6 +140,6 @@ function getErrorMessage(payload?: ResponseError): string { return getErrorMessage(payload.message); } -function getErrorMeta(payload?: ResponseError) { - return typeof payload === 'object' && 'meta' in payload ? payload.meta : undefined; +function getErrorAttributes(payload?: ResponseError): ResponseErrorAttributes | undefined { + return typeof payload === 'object' && 'attributes' in payload ? payload.attributes : undefined; } diff --git a/src/core/server/http/router/router.test.ts b/src/core/server/http/router/router.test.ts index 3e9f5e2d186b1..9fdf7297ed775 100644 --- a/src/core/server/http/router/router.test.ts +++ b/src/core/server/http/router/router.test.ts @@ -20,10 +20,12 @@ import { Router } from './router'; import { loggingServiceMock } from '../../logging/logging_service.mock'; const logger = loggingServiceMock.create().get(); +const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, {}); + describe('Router', () => { describe('Options', () => { it('throws if validation for a route is not defined explicitly', () => { - const router = new Router('', logger); + const router = new Router('', logger, enhanceWithContext); expect( // we use 'any' because validate is a required field () => router.get({ path: '/' } as any, (context, req, res) => res.ok({})) @@ -32,7 +34,7 @@ describe('Router', () => { ); }); it('throws if validation for a route is declared wrong', () => { - const router = new Router('', logger); + const router = new Router('', logger, enhanceWithContext); expect(() => router.get( // we use 'any' because validate requires @kbn/config-schema usage diff --git a/src/core/server/http/router/router.ts b/src/core/server/http/router/router.ts index 8f714c7b3c89a..3d9aaf4b3a811 100644 --- a/src/core/server/http/router/router.ts +++ b/src/core/server/http/router/router.ts @@ -26,6 +26,7 @@ import { KibanaRequest } from './request'; import { KibanaResponse, KibanaResponseFactory, kibanaResponseFactory } from './response'; import { RouteConfig, RouteConfigOptions, RouteMethod, RouteSchemas } from './route'; import { HapiResponseAdapter } from './response_adapter'; +import { RequestHandlerContext } from '../../../server'; interface RouterRoute { method: RouteMethod; @@ -148,7 +149,7 @@ export class Router implements IRouter { constructor( readonly routerPath: string, private readonly log: Logger, - private readonly enhanceWithContext: ContextEnhancer = fn => fn.bind(null, {}) + private readonly enhanceWithContext: ContextEnhancer ) { const buildMethod = (method: RouteMethod) => < P extends ObjectType, @@ -258,7 +259,7 @@ type RequestHandlerEnhanced< * @public */ export type RequestHandler

= ( - context: {}, + context: RequestHandlerContext, request: KibanaRequest, TypeOf, TypeOf>, response: KibanaResponseFactory ) => KibanaResponse | Promise>; diff --git a/src/core/server/http/router/socket.test.ts b/src/core/server/http/router/socket.test.ts index 6bd903fd2f36c..c813dcf3fc806 100644 --- a/src/core/server/http/router/socket.test.ts +++ b/src/core/server/http/router/socket.test.ts @@ -56,4 +56,50 @@ describe('KibanaSocket', () => { expect(socket.getPeerCertificate()).toBe(null); }); }); + + describe('authorized', () => { + it('returns `undefined` for net.Socket instance', () => { + const socket = new KibanaSocket(new Socket()); + + expect(socket.authorized).toBeUndefined(); + }); + + it('mirrors the value of tls.Socket.authorized', () => { + const tlsSocket = new TLSSocket(new Socket()); + + tlsSocket.authorized = true; + let socket = new KibanaSocket(tlsSocket); + expect(tlsSocket.authorized).toBe(true); + expect(socket.authorized).toBe(true); + + tlsSocket.authorized = false; + socket = new KibanaSocket(tlsSocket); + expect(tlsSocket.authorized).toBe(false); + expect(socket.authorized).toBe(false); + }); + }); + + describe('authorizationError', () => { + it('returns `undefined` for net.Socket instance', () => { + const socket = new KibanaSocket(new Socket()); + + expect(socket.authorizationError).toBeUndefined(); + }); + + it('mirrors the value of tls.Socket.authorizationError', () => { + const tlsSocket = new TLSSocket(new Socket()); + tlsSocket.authorizationError = undefined as any; + + let socket = new KibanaSocket(tlsSocket); + expect(tlsSocket.authorizationError).toBeUndefined(); + expect(socket.authorizationError).toBeUndefined(); + + const authorizationError = new Error('some error'); + tlsSocket.authorizationError = authorizationError; + socket = new KibanaSocket(tlsSocket); + + expect(tlsSocket.authorizationError).toBe(authorizationError); + expect(socket.authorizationError).toBe(authorizationError); + }); + }); }); diff --git a/src/core/server/http/router/socket.ts b/src/core/server/http/router/socket.ts index 2cdcd8f641001..83bf65a288c4b 100644 --- a/src/core/server/http/router/socket.ts +++ b/src/core/server/http/router/socket.ts @@ -37,10 +37,30 @@ export interface IKibanaSocket { * @returns An object representing the peer's certificate. */ getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate | null; + + /** + * Indicates whether or not the peer certificate was signed by one of the specified CAs. When TLS + * isn't used the value is `undefined`. + */ + readonly authorized?: boolean; + + /** + * The reason why the peer's certificate has not been verified. This property becomes available + * only when `authorized` is `false`. + */ + readonly authorizationError?: Error; } export class KibanaSocket implements IKibanaSocket { - constructor(private readonly socket: Socket) {} + readonly authorized?: boolean; + readonly authorizationError?: Error; + + constructor(private readonly socket: Socket) { + if (this.socket instanceof TLSSocket) { + this.authorized = this.socket.authorized; + this.authorizationError = this.socket.authorizationError; + } + } getPeerCertificate(detailed: true): DetailedPeerCertificate | null; getPeerCertificate(detailed: false): PeerCertificate | null; diff --git a/src/core/server/http/ssl_config.ts b/src/core/server/http/ssl_config.ts index c32b94cf26def..55d6ebff93ce7 100644 --- a/src/core/server/http/ssl_config.ts +++ b/src/core/server/http/ssl_config.ts @@ -49,13 +49,20 @@ export const sslSchema = schema.object( schema.oneOf([schema.literal('TLSv1'), schema.literal('TLSv1.1'), schema.literal('TLSv1.2')]), { defaultValue: ['TLSv1.1', 'TLSv1.2'], minSize: 1 } ), - requestCert: schema.maybe(schema.boolean({ defaultValue: false })), + clientAuthentication: schema.oneOf( + [schema.literal('none'), schema.literal('optional'), schema.literal('required')], + { defaultValue: 'none' } + ), }, { validate: ssl => { if (ssl.enabled && (!ssl.key || !ssl.certificate)) { return 'must specify [certificate] and [key] when ssl is enabled'; } + + if (!ssl.enabled && ssl.clientAuthentication !== 'none') { + return 'must enable ssl to use [clientAuthentication]'; + } }, } ); @@ -69,7 +76,8 @@ export class SslConfig { public certificate: string | undefined; public certificateAuthorities: string[] | undefined; public keyPassphrase: string | undefined; - public requestCert: boolean | undefined; + public requestCert: boolean; + public rejectUnauthorized: boolean; public cipherSuites: string[]; public supportedProtocols: string[]; @@ -86,7 +94,8 @@ export class SslConfig { this.keyPassphrase = config.keyPassphrase; this.cipherSuites = config.cipherSuites; this.supportedProtocols = config.supportedProtocols; - this.requestCert = config.requestCert; + this.requestCert = config.clientAuthentication !== 'none'; + this.rejectUnauthorized = config.clientAuthentication === 'required'; } /** diff --git a/src/core/server/http/types.ts b/src/core/server/http/types.ts new file mode 100644 index 0000000000000..a391b2e2e5d45 --- /dev/null +++ b/src/core/server/http/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 { IContextProvider, IContextContainer } from '../context'; +import { KibanaRequest, KibanaResponseFactory, KibanaResponse } from './router'; + +/** + * Parameters passed to the request handler function. + * @public + */ +export type RequestHandlerParams = [KibanaRequest, KibanaResponseFactory]; + +/** + * Expected outcome the request handler function. + * @public + */ +export type RequestHandlerReturn = KibanaResponse; + +/** + * An object that handles registration of http request context providers. + * @public + */ +export type RequestHandlerContextContainer = IContextContainer< + TContext, + RequestHandlerReturn | Promise, + RequestHandlerParams +>; + +/** + * Context provider for request handler. + * Extends request context object with provided functionality or data. + * + * @public + */ +export type RequestHandlerContextProvider = IContextProvider< + TContext, + keyof TContext, + RequestHandlerParams +>; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 5f6a273c8dd8c..ef31804be62b2 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -44,8 +44,15 @@ import { ClusterClient, ElasticsearchClientConfig, ElasticsearchServiceSetup, + ScopedClusterClient, } from './elasticsearch'; -import { HttpServiceSetup, HttpServiceStart, IRouter } from './http'; +import { + HttpServiceSetup, + HttpServiceStart, + IRouter, + RequestHandlerContextContainer, + RequestHandlerContextProvider, +} from './http'; import { PluginsServiceSetup, PluginsServiceStart, PluginOpaqueId } from './plugins'; import { ContextSetup } from './context'; @@ -76,6 +83,7 @@ export { HttpResponseOptions, HttpResponsePayload, HttpServerSetup, + ErrorHttpResponseOptions, IKibanaSocket, IsAuthenticated, KibanaRequest, @@ -89,8 +97,13 @@ export { OnPostAuthToolkit, RedirectResponseOptions, RequestHandler, + RequestHandlerContextContainer, + RequestHandlerContextProvider, + RequestHandlerParams, + RequestHandlerReturn, ResponseError, - ResponseErrorMeta, + ResponseErrorAttributes, + ResponseHeaders, kibanaResponseFactory, KibanaResponseFactory, RouteConfig, @@ -155,6 +168,21 @@ export { SavedObjectsMigrationVersion, } from './types'; +export { LegacyServiceSetupDeps, LegacyServiceStartDeps } from './legacy'; + +/** + * Plugin specific context passed to a route handler. + * @public + */ +export interface RequestHandlerContext { + core: { + elasticsearch: { + dataClient: ScopedClusterClient; + adminClient: ScopedClusterClient; + }; + }; +} + /** * Context passed to the plugins `setup` method. * @@ -179,6 +207,10 @@ export interface CoreSetup { registerOnPostAuth: HttpServiceSetup['registerOnPostAuth']; basePath: HttpServiceSetup['basePath']; isTlsEnabled: HttpServiceSetup['isTlsEnabled']; + registerRouteHandlerContext: ( + name: T, + provider: RequestHandlerContextProvider + ) => RequestHandlerContextContainer; createRouter: () => IRouter; }; } @@ -192,17 +224,15 @@ export interface CoreStart {} // eslint-disable-line @typescript-eslint/no-empty /** @internal */ export interface InternalCoreSetup { + context: ContextSetup; http: HttpServiceSetup; elasticsearch: ElasticsearchServiceSetup; - plugins: PluginsServiceSetup; } /** * @public */ -export interface InternalCoreStart { - plugins: PluginsServiceStart; -} +export interface InternalCoreStart {} // eslint-disable-line @typescript-eslint/no-empty-interface export { ContextSetup, diff --git a/src/core/server/legacy/index.ts b/src/core/server/legacy/index.ts index bb965c0272d14..84aec7077d407 100644 --- a/src/core/server/legacy/index.ts +++ b/src/core/server/legacy/index.ts @@ -20,4 +20,4 @@ /** @internal */ export { LegacyObjectToConfigAdapter } from './config/legacy_object_to_config_adapter'; /** @internal */ -export { LegacyService } from './legacy_service'; +export { LegacyService, LegacyServiceSetupDeps, LegacyServiceStartDeps } from './legacy_service'; diff --git a/src/core/server/legacy/integration_tests/legacy_service.test.ts b/src/core/server/legacy/integration_tests/legacy_service.test.ts index 67e05f9a7276e..da2550f2ae799 100644 --- a/src/core/server/legacy/integration_tests/legacy_service.test.ts +++ b/src/core/server/legacy/integration_tests/legacy_service.test.ts @@ -32,7 +32,7 @@ describe('legacy service', () => { const rootUrl = '/route'; const router = http.createRouter(rootUrl); router.get({ path: '/new-platform', validate: false }, (context, req, res) => - res.ok({ content: 'from-new-platform' }) + res.ok({ body: 'from-new-platform' }) ); await root.start(); @@ -45,9 +45,7 @@ describe('legacy service', () => { handler: () => 'ok from legacy server', }); - await kbnTestServer.request - .get(root, '/route/new-platform') - .expect(200, { content: 'from-new-platform' }); + await kbnTestServer.request.get(root, '/route/new-platform').expect(200, 'from-new-platform'); await kbnTestServer.request.get(root, legacyPlatformUrl).expect(200, 'ok from legacy server'); }); @@ -56,7 +54,7 @@ describe('legacy service', () => { const rootUrl = '/route'; const router = http.createRouter(rootUrl); router.get({ path: '', validate: false }, (context, req, res) => - res.ok({ content: 'from-new-platform' }) + res.ok({ body: 'from-new-platform' }) ); await root.start(); diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index 7da013dbe2174..9d208445a0a1f 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -27,6 +27,8 @@ import { LegacyService } from '.'; import MockClusterManager from '../../../cli/cluster/cluster_manager'; import KbnServer from '../../../legacy/server/kbn_server'; import { Config, Env, ObjectToConfigAdapter } from '../config'; +import { ContextSetup } from '../context'; +import { contextServiceMock } from '../context/context_service.mock'; import { getEnvOptions } from '../config/__mocks__/env'; import { configServiceMock } from '../config/config_service.mock'; import { ElasticsearchServiceSetup } from '../elasticsearch'; @@ -42,6 +44,7 @@ let env: Env; let config$: BehaviorSubject; let setupDeps: { core: { + context: ContextSetup; elasticsearch: ElasticsearchServiceSetup; http: any; plugins: PluginsServiceSetup; @@ -69,6 +72,7 @@ beforeEach(() => { setupDeps = { core: { + context: contextServiceMock.createSetupContract(), elasticsearch: { legacy: {} } as any, http: { auth: { diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index a50f049db2231..612c46cd3bbc5 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -26,6 +26,7 @@ import { CoreContext } from '../core_context'; import { DevConfig, DevConfigType } from '../dev'; import { BasePathProxyServer, HttpConfig, HttpConfigType } from '../http'; import { Logger } from '../logging'; +import { PluginsServiceSetup, PluginsServiceStart } from '../plugins'; interface LegacyKbnServer { applyLoggingConfiguration: (settings: Readonly>) => void; @@ -46,13 +47,25 @@ function getLegacyRawConfig(config: Config) { return rawConfig; } -interface SetupDeps { - core: InternalCoreSetup; +/** + * @public + * @deprecated + */ +export interface LegacyServiceSetupDeps { + core: InternalCoreSetup & { + plugins: PluginsServiceSetup; + }; plugins: Record; } -interface StartDeps { - core: InternalCoreStart; +/** + * @public + * @deprecated + */ +export interface LegacyServiceStartDeps { + core: InternalCoreStart & { + plugins: PluginsServiceStart; + }; plugins: Record; } @@ -63,7 +76,7 @@ export class LegacyService implements CoreService { private readonly httpConfig$: Observable; private kbnServer?: LegacyKbnServer; private configSubscription?: Subscription; - private setupDeps?: SetupDeps; + private setupDeps?: LegacyServiceSetupDeps; constructor(private readonly coreContext: CoreContext) { this.log = coreContext.logger.get('legacy-service'); @@ -74,10 +87,10 @@ export class LegacyService implements CoreService { .atPath('server') .pipe(map(rawConfig => new HttpConfig(rawConfig, coreContext.env))); } - public async setup(setupDeps: SetupDeps) { + public async setup(setupDeps: LegacyServiceSetupDeps) { this.setupDeps = setupDeps; } - public async start(startDeps: StartDeps) { + public async start(startDeps: LegacyServiceStartDeps) { const { setupDeps } = this; if (!setupDeps) { throw new Error('Legacy service is not setup yet.'); @@ -143,7 +156,11 @@ export class LegacyService implements CoreService { ); } - private async createKbnServer(config: Config, setupDeps: SetupDeps, startDeps: StartDeps) { + private async createKbnServer( + config: Config, + setupDeps: LegacyServiceSetupDeps, + startDeps: LegacyServiceStartDeps + ) { // eslint-disable-next-line @typescript-eslint/no-var-requires const KbnServer = require('../../../legacy/server/kbn_server'); const kbnServer: LegacyKbnServer = new KbnServer(getLegacyRawConfig(config), { diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index e7ff83d7ad405..f072ae5fd4dbd 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -67,6 +67,7 @@ function createCoreSetupMock() { basePath: httpService.basePath, isTlsEnabled: httpService.isTlsEnabled, createRouter: jest.fn(), + registerRouteHandlerContext: jest.fn(), }; httpMock.createRouter.mockImplementation(() => httpService.createRouter('')); diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index cbe911b2afa68..46432cbb0da75 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -109,7 +109,11 @@ export function createPluginSetupContext( }, http: { createCookieSessionStorageFactory: deps.http.createCookieSessionStorageFactory, - createRouter: () => deps.http.createRouter(`/${plugin.name}`), + registerRouteHandlerContext: deps.http.registerRouteHandlerContext.bind( + null, + plugin.opaqueId + ), + createRouter: () => deps.http.createRouter('', plugin.opaqueId), registerOnPreAuth: deps.http.registerOnPreAuth, registerAuth: deps.http.registerAuth, registerOnPostAuth: deps.http.registerOnPostAuth, diff --git a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts index d96d43eb9e7f6..f850954e84323 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts @@ -20,7 +20,7 @@ import Boom from 'boom'; import { getProperty, IndexMapping } from '../../../mappings'; -const TOP_LEVEL_FIELDS = ['_id']; +const TOP_LEVEL_FIELDS = ['_id', '_score']; export function getSortingParams( mappings: IndexMapping, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 6597fdf0259d4..94c7f6ec9b325 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -121,6 +121,7 @@ export interface CoreSetup { registerOnPostAuth: HttpServiceSetup['registerOnPostAuth']; basePath: HttpServiceSetup['basePath']; isTlsEnabled: HttpServiceSetup['isTlsEnabled']; + registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; createRouter: () => IRouter; }; } @@ -130,7 +131,9 @@ export interface CoreStart { } // @public -export interface CustomHttpResponseOptions extends HttpResponseOptions { +export interface CustomHttpResponseOptions { + body?: T; + headers?: ResponseHeaders; // (undocumented) statusCode: number; } @@ -182,6 +185,12 @@ export interface ElasticsearchServiceSetup { }; } +// @public +export interface ErrorHttpResponseOptions { + body?: ResponseError; + headers?: ResponseHeaders; +} + // @public export interface FakeRequest { headers: Headers; @@ -205,7 +214,7 @@ export type Headers = { // @public export interface HttpResponseOptions { - // Warning: (ae-forgotten-export) The symbol "ResponseHeaders" needs to be exported by the entry point index.d.ts + body?: HttpResponsePayload; headers?: ResponseHeaders; } @@ -239,7 +248,8 @@ export interface HttpServerSetup { // @public (undocumented) export type HttpServiceSetup = Omit & { - createRouter: (path: string) => IRouter; + createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter; + registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer; }; // @public (undocumented) @@ -261,6 +271,8 @@ export type IContextProvider, TContextName // @public export interface IKibanaSocket { + readonly authorizationError?: Error; + readonly authorized?: boolean; // (undocumented) getPeerCertificate(detailed: true): DetailedPeerCertificate | null; // (undocumented) @@ -270,18 +282,16 @@ export interface IKibanaSocket { // @internal (undocumented) export interface InternalCoreSetup { + // (undocumented) + context: ContextSetup; // (undocumented) elasticsearch: ElasticsearchServiceSetup; // (undocumented) http: HttpServiceSetup; - // (undocumented) - plugins: PluginsServiceSetup; } // @public (undocumented) export interface InternalCoreStart { - // (undocumented) - plugins: PluginsServiceStart; } // @public @@ -337,23 +347,20 @@ export type KibanaResponseFactory = typeof kibanaResponseFactory; // @public export const kibanaResponseFactory: { - custom: (payload: string | Error | Record | Buffer | Stream | { - message: string | Error; - meta?: ResponseErrorMeta | undefined; - } | undefined, options: CustomHttpResponseOptions) => KibanaResponse | Buffer | Stream | { + custom: | Buffer | Stream | { message: string | Error; - meta?: ResponseErrorMeta | undefined; - }>; - badRequest: (error?: ResponseError, options?: HttpResponseOptions) => KibanaResponse; - unauthorized: (error?: ResponseError, options?: HttpResponseOptions) => KibanaResponse; - forbidden: (error?: ResponseError, options?: HttpResponseOptions) => KibanaResponse; - notFound: (error?: ResponseError, options?: HttpResponseOptions) => KibanaResponse; - conflict: (error?: ResponseError, options?: HttpResponseOptions) => KibanaResponse; - internalError: (error?: ResponseError, options?: HttpResponseOptions) => KibanaResponse; - customError: (error: ResponseError, options: CustomHttpResponseOptions) => KibanaResponse; - redirected: (payload: HttpResponsePayload, options: RedirectResponseOptions) => KibanaResponse | Buffer | Stream>; - ok: (payload: HttpResponsePayload, options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; - accepted: (payload?: HttpResponsePayload, options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; + attributes?: Record | undefined; + } | undefined>(options: CustomHttpResponseOptions) => KibanaResponse; + badRequest: (options?: ErrorHttpResponseOptions) => KibanaResponse; + unauthorized: (options?: ErrorHttpResponseOptions) => KibanaResponse; + forbidden: (options?: ErrorHttpResponseOptions) => KibanaResponse; + notFound: (options?: ErrorHttpResponseOptions) => KibanaResponse; + conflict: (options?: ErrorHttpResponseOptions) => KibanaResponse; + internalError: (options?: ErrorHttpResponseOptions) => KibanaResponse; + customError: (options: CustomHttpResponseOptions) => KibanaResponse; + redirected: (options: RedirectResponseOptions) => KibanaResponse | Buffer | Stream>; + ok: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; + accepted: (options?: HttpResponseOptions) => KibanaResponse | Buffer | Stream>; noContent: (options?: HttpResponseOptions) => KibanaResponse; }; @@ -366,6 +373,28 @@ export type KnownHeaders = KnownKeys; export interface LegacyRequest extends Request { } +// @public @deprecated (undocumented) +export interface LegacyServiceSetupDeps { + // Warning: (ae-incompatible-release-tags) The symbol "core" is marked as @public, but its signature references "InternalCoreSetup" which is marked as @internal + // + // (undocumented) + core: InternalCoreSetup & { + plugins: PluginsServiceSetup; + }; + // (undocumented) + plugins: Record; +} + +// @public @deprecated (undocumented) +export interface LegacyServiceStartDeps { + // (undocumented) + core: InternalCoreStart & { + plugins: PluginsServiceStart; + }; + // (undocumented) + plugins: Record; +} + // Warning: (ae-forgotten-export) The symbol "lifecycleResponseFactory" needs to be exported by the entry point index.d.ts // // @public @@ -541,23 +570,46 @@ export type RedirectResponseOptions = HttpResponseOptions & { }; // @public -export type RequestHandler

= (context: {}, request: KibanaRequest, TypeOf, TypeOf>, response: KibanaResponseFactory) => KibanaResponse | Promise>; +export type RequestHandler

= (context: RequestHandlerContext, request: KibanaRequest, TypeOf, TypeOf>, response: KibanaResponseFactory) => KibanaResponse | Promise>; + +// @public +export interface RequestHandlerContext { + // (undocumented) + core: { + elasticsearch: { + dataClient: ScopedClusterClient; + adminClient: ScopedClusterClient; + }; + }; +} + +// @public +export type RequestHandlerContextContainer = IContextContainer, RequestHandlerParams>; + +// @public +export type RequestHandlerContextProvider = IContextProvider; + +// @public +export type RequestHandlerParams = [KibanaRequest, KibanaResponseFactory]; + +// @public +export type RequestHandlerReturn = KibanaResponse; // @public export type ResponseError = string | Error | { message: string | Error; - meta?: ResponseErrorMeta; + attributes?: ResponseErrorAttributes; }; // @public -export interface ResponseErrorMeta { - // (undocumented) - data?: Record; - // (undocumented) - docLink?: string; - // (undocumented) - errorCode?: string; -} +export type ResponseErrorAttributes = Record; + +// @public +export type ResponseHeaders = { + [header in KnownHeaders]?: string | string[]; +} & { + [header: string]: string | string[]; +}; // @public export interface RouteConfig

{ diff --git a/src/core/server/server.ts b/src/core/server/server.ts index a78c2e2a23c4a..e0569ed80fca4 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -17,6 +17,7 @@ * under the License. */ import { Observable } from 'rxjs'; +import { take } from 'rxjs/operators'; import { Type } from '@kbn/config-schema'; import { ConfigService, Env, Config, ConfigPath } from './config'; @@ -32,6 +33,9 @@ import { config as loggingConfig } from './logging'; import { config as devConfig } from './dev'; import { mapToObject } from '../utils/'; import { ContextService } from './context'; +import { InternalCoreSetup } from './index'; + +const coreId = Symbol('core'); export class Server { public readonly configService: ConfigService; @@ -50,7 +54,7 @@ export class Server { this.log = this.logger.get('server'); this.configService = new ConfigService(config$, env, logger); - const core = { coreId: Symbol('core'), configService: this.configService, env, logger }; + const core = { coreId, configService: this.configService, env, logger }; this.context = new ContextService(core); this.http = new HttpService(core); this.plugins = new PluginsService(core); @@ -63,30 +67,29 @@ export class Server { // Discover any plugins before continuing. This allows other systems to utilize the plugin dependency graph. const pluginDependencies = await this.plugins.discover(); + const contextServiceSetup = this.context.setup({ pluginDependencies }); + + const httpSetup = await this.http.setup({ + context: contextServiceSetup, + }); - const httpSetup = await this.http.setup(); this.registerDefaultRoute(httpSetup); - const contextServiceSetup = this.context.setup({ pluginDependencies }); const elasticsearchServiceSetup = await this.elasticsearch.setup({ http: httpSetup, }); - const pluginsSetup = await this.plugins.setup({ - context: contextServiceSetup, - elasticsearch: elasticsearchServiceSetup, - http: httpSetup, - }); - const coreSetup = { context: contextServiceSetup, elasticsearch: elasticsearchServiceSetup, http: httpSetup, - plugins: pluginsSetup, }; + this.registerCoreContext(coreSetup); + const pluginsSetup = await this.plugins.setup(coreSetup); + await this.legacy.setup({ - core: coreSetup, + core: { ...coreSetup, plugins: pluginsSetup }, plugins: mapToObject(pluginsSetup.contracts), }); @@ -121,10 +124,23 @@ export class Server { private registerDefaultRoute(httpSetup: HttpServiceSetup) { const router = httpSetup.createRouter('/core'); router.get({ path: '/', validate: false }, async (context, req, res) => - res.ok({ version: '0.0.1' }) + res.ok({ body: { version: '0.0.1' } }) ); } + private registerCoreContext(coreSetup: InternalCoreSetup) { + coreSetup.http.registerRouteHandlerContext(coreId, 'core', async (context, req) => { + const adminClient = await coreSetup.elasticsearch.adminClient$.pipe(take(1)).toPromise(); + const dataClient = await coreSetup.elasticsearch.dataClient$.pipe(take(1)).toPromise(); + return { + elasticsearch: { + adminClient: adminClient.asScoped(req), + dataClient: dataClient.asScoped(req), + }, + }; + }); + } + public async setupConfigSchemas() { const schemas: Array<[ConfigPath, Type]> = [ [elasticsearchConfig.path, elasticsearchConfig.schema], diff --git a/src/core/utils/context.mock.ts b/src/core/utils/context.mock.ts index a3849fb77f830..4d91c11542b2f 100644 --- a/src/core/utils/context.mock.ts +++ b/src/core/utils/context.mock.ts @@ -24,8 +24,13 @@ export type ContextContainerMock = jest.Mocked> const createContextMock = () => { const contextMock: ContextContainerMock = { registerContext: jest.fn(), - createHandler: jest.fn(), + createHandler: jest.fn((id, handler) => (...args: any[]) => + Promise.resolve(handler({}, ...args)) + ), }; + contextMock.createHandler.mockImplementation((pluginId, handler) => (...args) => + handler({}, ...args) + ); return contextMock; }; diff --git a/src/core/utils/pick.ts b/src/core/utils/pick.ts index d55c76a3ca77d..77854f9af680b 100644 --- a/src/core/utils/pick.ts +++ b/src/core/utils/pick.ts @@ -17,10 +17,7 @@ * under the License. */ -export function pick, K extends keyof T>( - obj: T, - keys: K[] -): Pick { +export function pick(obj: T, keys: K[]): Pick { return keys.reduce( (acc, key) => { if (obj.hasOwnProperty(key)) { diff --git a/src/core/utils/poller.test.ts b/src/core/utils/poller.test.ts new file mode 100644 index 0000000000000..df89f7341c956 --- /dev/null +++ b/src/core/utils/poller.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 { Poller } from './poller'; + +const delay = (duration: number) => new Promise(r => setTimeout(r, duration)); + +// FLAKY: https://github.com/elastic/kibana/issues/44560 +describe.skip('Poller', () => { + let handler: jest.Mock; + let poller: Poller; + + beforeEach(() => { + handler = jest.fn().mockImplementation((iteration: number) => `polling-${iteration}`); + poller = new Poller(100, 'polling', handler); + }); + + afterEach(() => { + poller.unsubscribe(); + }); + + it('returns an observable of subject', async () => { + await delay(300); + expect(poller.subject$.getValue()).toBe('polling-2'); + }); + + it('executes a function on an interval', async () => { + await delay(300); + expect(handler).toBeCalledTimes(3); + }); + + it('no longer polls after unsubscribing', async () => { + await delay(300); + poller.unsubscribe(); + await delay(300); + expect(handler).toBeCalledTimes(3); + }); + + it('does not add next value if returns undefined', async () => { + const values: any[] = []; + const polling = new Poller(100, 'polling', iteration => { + if (iteration % 2 === 0) { + return `polling-${iteration}`; + } + }); + + polling.subject$.subscribe(value => { + values.push(value); + }); + await delay(300); + polling.unsubscribe(); + + expect(values).toEqual(['polling', 'polling-0', 'polling-2']); + }); +}); diff --git a/src/core/utils/poller.ts b/src/core/utils/poller.ts new file mode 100644 index 0000000000000..7c50db74bcefb --- /dev/null +++ b/src/core/utils/poller.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 { BehaviorSubject, timer } from 'rxjs'; + +/** + * Create an Observable BehaviorSubject to invoke a function on an interval + * which returns the next value for the observable. + * @public + */ +export class Poller { + /** + * The observable to observe for changes to the poller value. + */ + public readonly subject$ = new BehaviorSubject(this.initialValue); + private poller$ = timer(0, this.frequency); + private subscription = this.poller$.subscribe(async iteration => { + const next = await this.handler(iteration); + + if (next !== undefined) { + this.subject$.next(next); + } + + return iteration; + }); + + constructor( + private frequency: number, + private initialValue: T, + private handler: (iteration: number) => Promise | T | undefined + ) {} + + /** + * Permanently end the polling operation. + */ + unsubscribe() { + return this.subscription.unsubscribe(); + } +} diff --git a/src/dev/build/tasks/create_empty_dirs_and_files_task.js b/src/dev/build/tasks/create_empty_dirs_and_files_task.js index 7badb1c498902..6bf059ca9519b 100644 --- a/src/dev/build/tasks/create_empty_dirs_and_files_task.js +++ b/src/dev/build/tasks/create_empty_dirs_and_files_task.js @@ -25,8 +25,8 @@ export const CreateEmptyDirsAndFilesTask = { async run(config, log, build) { await Promise.all([ mkdirp(build.resolvePath('plugins')), - mkdirp(build.resolvePath('data')), - write(build.resolvePath('optimize/.babel_register_cache.json'), '{}'), + mkdirp(build.resolvePath('data/optimize')), + write(build.resolvePath('data/optimize/.babel_register_cache.json'), '{}'), ]); }, }; diff --git a/src/dev/build/tasks/nodejs/__tests__/node_shasums.js b/src/dev/build/tasks/nodejs/__tests__/node_shasums.js deleted file mode 100644 index 3e400283dbd80..0000000000000 --- a/src/dev/build/tasks/nodejs/__tests__/node_shasums.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. - */ - -import expect from '@kbn/expect'; - -import { getNodeShasums } from '../node_shasums'; - -describe('src/dev/build/tasks/nodejs/node_shasums', () => { - it('resolves to an object with shasums for node downloads for version', async () => { - const shasums = await getNodeShasums('8.9.4'); - expect(shasums).to.have.property('node-v8.9.4.tar.gz'); - }); -}); diff --git a/src/dev/build/tasks/nodejs/node_shasums.js b/src/dev/build/tasks/nodejs/node_shasums.js deleted file mode 100644 index 150e9d4f1508b..0000000000000 --- a/src/dev/build/tasks/nodejs/node_shasums.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. - */ - -import wreck from '@hapi/wreck'; - -export async function getNodeShasums(nodeVersion) { - const url = `https://nodejs.org/dist/v${nodeVersion}/SHASUMS256.txt`; - - const { res, payload } = await wreck.get(url); - - if (res.statusCode !== 200) { - throw new Error(`${url} failed with a ${res.statusCode} response`); - } - - return payload - .toString('utf8') - .split('\n') - .reduce((acc, line) => { - const [sha, platform] = line.split(' '); - - return { - ...acc, - [platform]: sha, - }; - }, {}); -} diff --git a/src/dev/build/tasks/nodejs/node_shasums.test.ts b/src/dev/build/tasks/nodejs/node_shasums.test.ts new file mode 100644 index 0000000000000..ee91d2a370fb1 --- /dev/null +++ b/src/dev/build/tasks/nodejs/node_shasums.test.ts @@ -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. + */ + +const mockResponse = `155ae63f0bb47050e0c31b4f8c17dadc79dcfa8e8f4ec9e3974fd7592afa9a4f node-v8.9.4-aix-ppc64.tar.gz +ca50f7d2035eb805306e303b644bb1cde170ce2615e0a2c6e95fb80881c48c24 node-v8.9.4-darwin-x64.tar.gz +cb79e2da37d2b646a06adaddcda67ff6ba0f77f9ca733b041dabf3dad79c7468 node-v8.9.4-darwin-x64.tar.xz +ef7248e81706daeeec946c19808a50b60ac250e648365d78fda6e40f1f9b23a5 node-v8.9.4-headers.tar.gz +11ed407a4bc3d8c3e73305ac54e91e64c9a9f6a2ae5476791d6fcc14ac159bfc node-v8.9.4-headers.tar.xz +2b133c7d23033fbc2419e66fc08bba35c427a97aba83ed6848b6b4678c0cac65 node-v8.9.4-linux-arm64.tar.gz +7c0369a5dbc98d0989c208ca3ee1b6db4cba576343014fdbf7d36fd2659f7089 node-v8.9.4-linux-arm64.tar.xz +81f138e935323246bd5da518eb0ea8ad00008f3c8a8d606e17589a545a9c73d1 node-v8.9.4-linux-armv6l.tar.gz +501bcae62ea1769924facc9628f407d37753e7a024cf3b12a18ea9dab1b380c9 node-v8.9.4-linux-armv6l.tar.xz +a0dd9009cb8d4be89c8a31131df16ad5ea1580d10ae426c5142aa34b0ad4ea76 node-v8.9.4-linux-armv7l.tar.gz +fe19f195df3d4f362d0cf0eef43c1a6a0b6006a1be2a89ee1808091c2ef4d722 node-v8.9.4-linux-armv7l.tar.xz +c5df73b8571edf97f83b484d6139332fad3b710d51be4aeb8d846059862d4675 node-v8.9.4-linux-ppc64le.tar.gz +21178be5e4c1dbdd99610d24aa934234a368c542ebabb3d98c31d393cf4adf06 node-v8.9.4-linux-ppc64le.tar.xz +d6e53ab2f8364528d4c6800adc1e7fccec607fd07a97b83985732c749a7fc846 node-v8.9.4-linux-s390x.tar.gz +90c6c284db9482a478dd5110e2171435156d56a013aeda2f636b6240eba156bd node-v8.9.4-linux-s390x.tar.xz +21fb4690e349f82d708ae766def01d7fec1b085ce1f5ab30d9bda8ee126ca8fc node-v8.9.4-linux-x64.tar.gz +68b94aac38cd5d87ab79c5b38306e34a20575f31a3ea788d117c20fffcca3370 node-v8.9.4-linux-x64.tar.xz +cc2f7a300353422ede336f5e72b71f0d6eac46732a31b7640648378830dd7513 node-v8.9.4-linux-x86.tar.gz +79f241f31eab5dfe2976fb0633c598dababd207ab0b8a163004f296cd7794a65 node-v8.9.4-linux-x86.tar.xz +b93767f7e186b1ae7204fedafa4110534f577d18d4204f422b626afdd5061e28 node-v8.9.4.pkg +e4a5d945091043c937125cd0d515258785cd4ea806fe3b77000d888de23d2ba0 node-v8.9.4-sunos-x64.tar.gz +b33e8f1495b88fcc0ab1e2579f2f7cf4d39886d577430dcb920a024829d4cf28 node-v8.9.4-sunos-x64.tar.xz +551729411793e427f5760fe8e46f45612e1e8e7c63e55ad34243ebf8ea9a4a7a node-v8.9.4-sunos-x86.tar.gz +6b439bb7204362c0af7a654bce24fcf8059e1772b2f0a9e4e1f8a0b8caa85d26 node-v8.9.4-sunos-x86.tar.xz +729b44b32b2f82ecd5befac4f7518de0c4e3add34e8fe878f745740a66cbbc01 node-v8.9.4.tar.gz +6cdcde9c9c1ca9f450a0b24eafa229ca759e576daa0fae892ce74d541ecdc86f node-v8.9.4.tar.xz +15a847a28358f9ae40bae42f49b033b0180bc10661632c63a9c8487ae980a8ba node-v8.9.4-win-x64.7z +48946e99ac4484e071df25741d2300f3a656f476c5ff3f8116a4746c07ebe3b7 node-v8.9.4-win-x64.zip +50ad674fb4c89edf35d3fee2136da86631cb7c0504589eb71ce8a3bb176493ed node-v8.9.4-win-x86.7z +02e3c65000ac055e05c604aec4cf318212efbd4b60a945ed319072d58314ca32 node-v8.9.4-win-x86.zip +547689da69bacadfee619d208702b73698d14297bd5fef5d80656897989e91b6 node-v8.9.4-x64.msi +f9442188c2f66d167a0ac610dee6d16e226ba28ca93f9569e0276268eb8f85dc node-v8.9.4-x86.msi +b73841f25d6e75d635770fd1a32e4d74d6ab2feed0fd7708bb40b967ae06f33e win-x64/node.exe +5439dc6f0d632ecdeb7342986743a03fe0818e34f0a67e38de74fa9c94886a39 win-x64/node.lib +6ab35445dd564978019cf4f3cfe11dd342b8450015fc054df99aa6f35f21736a win-x64/node_pdb.7z +c064abba981c2373e7e1a8c53b4e4ed1d4927bd9c0f7c065b24dd13b731598bd win-x64/node_pdb.zip +c8430b20cd067d8784d5faae04f9447987a472b22b6d0a2403ea4362ecd3d0bc win-x86/node.exe +c4edece2c0aa68e816c4e067f397eb12e9d0c81bb37b3d349dbaf47cf246b0b7 win-x86/node.lib +6a2ee7a0b0074ece27d171418d82ce25a60b87750ec30c5c9fbeaaca8c206fa5 win-x86/node_pdb.7z +1b44176d888c1bc6a6b05fcc6234031b3b8a58da9de8b99661088f998ac5e269 win-x86/node_pdb.zip`; + +jest.mock('axios', () => ({ + async get(url: string) { + expect(url).toBe('https://nodejs.org/dist/v8.9.4/SHASUMS256.txt'); + return { + status: 200, + data: mockResponse, + }; + }, +})); + +import { getNodeShasums } from './node_shasums'; + +describe('src/dev/build/tasks/nodejs/node_shasums', () => { + it('resolves to an object with shasums for node downloads for version', async () => { + const shasums = await getNodeShasums('8.9.4'); + expect(shasums).toEqual( + expect.objectContaining({ + 'node-v8.9.4.tar.gz': '729b44b32b2f82ecd5befac4f7518de0c4e3add34e8fe878f745740a66cbbc01', + 'node-v8.9.4-win-x64.zip': + '48946e99ac4484e071df25741d2300f3a656f476c5ff3f8116a4746c07ebe3b7', + }) + ); + }); +}); diff --git a/src/dev/build/tasks/nodejs/node_shasums.ts b/src/dev/build/tasks/nodejs/node_shasums.ts new file mode 100644 index 0000000000000..1b8d01a9b1d94 --- /dev/null +++ b/src/dev/build/tasks/nodejs/node_shasums.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 axios from 'axios'; + +export async function getNodeShasums(nodeVersion: string) { + const url = `https://nodejs.org/dist/v${nodeVersion}/SHASUMS256.txt`; + + const { status, data } = await axios.get(url); + + if (status !== 200) { + throw new Error(`${url} failed with a ${status} response`); + } + + return data + .toString('utf8') + .split('\n') + .reduce((acc: Record, line: string) => { + const [sha, platform] = line.split(' '); + + return { + ...acc, + [platform]: sha, + }; + }, {}); +} diff --git a/src/dev/build/tasks/nodejs_modules/webpack_dll.js b/src/dev/build/tasks/nodejs_modules/webpack_dll.js index 07ca8230a1585..e741784e7f866 100644 --- a/src/dev/build/tasks/nodejs_modules/webpack_dll.js +++ b/src/dev/build/tasks/nodejs_modules/webpack_dll.js @@ -18,9 +18,10 @@ */ import { deleteAll, isFileAccessible, read, write } from '../../lib'; -import { dirname, sep, relative, resolve } from 'path'; +import { dirname, relative, resolve } from 'path'; import pkgUp from 'pkg-up'; import globby from 'globby'; +import normalizePosixPath from 'normalize-path'; function checkDllEntryAccess(entry, baseDir = '') { const resolvedPath = baseDir ? resolve(baseDir, entry) : entry; @@ -48,7 +49,7 @@ export async function getDllEntries(manifestPath, whiteListedModules, baseDir = // Only includes modules who are not in the white list of modules // and that are node_modules return modules.filter(entry => { - const isWhiteListed = whiteListedModules.some(nonEntry => entry.includes(`node_modules${sep}${nonEntry}${sep}`)); + const isWhiteListed = whiteListedModules.some(nonEntry => normalizePosixPath(entry).includes(`node_modules/${nonEntry}`)); const isNodeModule = entry.includes('node_modules'); // NOTE: when using dynamic imports on webpack the entry paths could be created @@ -69,6 +70,7 @@ export async function cleanDllModuleFromEntryPath(logger, entryPath) { const modulePkgPath = await pkgUp(entryPath); const modulePkg = JSON.parse(await read(modulePkgPath)); const moduleDir = dirname(modulePkgPath); + const normalizedModuleDir = normalizePosixPath(moduleDir); // Cancel the cleanup for this module as it // was already done. @@ -93,9 +95,9 @@ export async function cleanDllModuleFromEntryPath(logger, entryPath) { // until the following issue gets closed // https://github.com/sindresorhus/globby/issues/87 const filesToDelete = await globby([ - `${moduleDir}/**`, - `!${moduleDir}/**/*.+(css)`, - `!${moduleDir}/**/*.+(gif|ico|jpeg|jpg|tiff|tif|svg|png|webp)`, + `${normalizedModuleDir}/**`, + `!${normalizedModuleDir}/**/*.+(css)`, + `!${normalizedModuleDir}/**/*.+(gif|ico|jpeg|jpg|tiff|tif|svg|png|webp)`, ]); await deleteAll(filesToDelete.filter(path => { diff --git a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh index dd8638a0c20bf..9cf08ea38254d 100644 --- a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh +++ b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh @@ -34,6 +34,5 @@ case $1 in ;; esac -chown -R <%= user %>:<%= group %> <%= optimizeDir %> -chown <%= user %>:<%= group %> <%= dataDir %> +chown -R <%= user %>:<%= group %> <%= dataDir %> chown <%= user %>:<%= group %> <%= pluginsDir %> diff --git a/src/dev/build/tasks/os_packages/package_scripts/post_remove.sh b/src/dev/build/tasks/os_packages/package_scripts/post_remove.sh index 25c46a54a222a..1ff2dbee675bd 100644 --- a/src/dev/build/tasks/os_packages/package_scripts/post_remove.sh +++ b/src/dev/build/tasks/os_packages/package_scripts/post_remove.sh @@ -44,10 +44,6 @@ if [ "$REMOVE_USER_AND_GROUP" = "true" ]; then fi if [ "$REMOVE_DIRS" = "true" ]; then - if [ -d "<%= optimizeDir %>" ]; then - rm -rf "<%= optimizeDir %>" - fi - if [ -d "<%= pluginsDir %>" ]; then rm -rf "<%= pluginsDir %>" fi diff --git a/src/dev/build/tasks/os_packages/run_fpm.js b/src/dev/build/tasks/os_packages/run_fpm.js index cb3c560d6725a..7272d7013a321 100644 --- a/src/dev/build/tasks/os_packages/run_fpm.js +++ b/src/dev/build/tasks/os_packages/run_fpm.js @@ -89,7 +89,6 @@ export async function runFpm(config, log, build, type, pkgSpecificFlags) { // scripts, also causes scripts to be processed with erb '--template-value', `user=kibana`, '--template-value', `group=kibana`, - '--template-value', `optimizeDir=/usr/share/kibana/optimize`, '--template-value', `configDir=/etc/kibana`, '--template-value', `pluginsDir=/usr/share/kibana/plugins`, '--template-value', `dataDir=/var/lib/kibana`, diff --git a/src/dev/ci_setup/get_percy_env.js b/src/dev/ci_setup/get_percy_env.js index ead64fd2b9056..ddf3e0da3e9d4 100644 --- a/src/dev/ci_setup/get_percy_env.js +++ b/src/dev/ci_setup/get_percy_env.js @@ -23,7 +23,32 @@ const pkg = require('../../../package.json'); const { stdout: commit } = execa.sync('git', ['rev-parse', 'HEAD']); const shortCommit = commit.slice(0, 8); -const isPr = process.env.JOB_NAME.includes('elastic+kibana+pull-request'); +const isPr = !!process.env.ghprbPullId; +if (isPr && !(process.env.PR_TARGET_BRANCH && process.env.PR_SOURCE_BRANCH)) { + throw new Error( + 'getPercyEnv: Unable to determine percy environment in prs without [PR_TARGET_BRANCH] and [PR_SOURCE_BRANCH] environment variables' + ); +} + +let branch; +if (isPr) { + branch = process.env.PR_SOURCE_BRANCH; +} else { + if (!process.env.branch_specifier) { + throw new Error('getPercyEnv: [branch_specifier] environment variable required'); + } + + branch = process.env.branch_specifier.split('refs/heads/')[1]; + + if (!branch) { + throw new Error( + `getPercyEnv: [branch_specifier=${process.env.branch_specifier}] must start with 'refs/heads/'` + ); + } +} console.log(`export PERCY_PARALLEL_TOTAL=2;`); -console.log(`export PERCY_PARALLEL_NONCE="${shortCommit}/${isPr ? 'PR' : pkg.branch}/${process.env.BUILD_ID}";`); +console.log(`export PERCY_PARALLEL_NONCE="${shortCommit}/${isPr ? 'PR' : branch}/${process.env.BUILD_ID}";`); +console.log(`export PERCY_BRANCH="${branch}";`); +// percy snapshots always target pkg.branch, so that feature branches can be based on master/7.x/etc. +console.log(`export PERCY_TARGET_BRANCH="${isPr ? process.env.PR_TARGET_BRANCH : pkg.branch}";`); diff --git a/src/dev/ci_setup/setup.sh b/src/dev/ci_setup/setup.sh index 951a83c091ec8..104a818f72a20 100755 --- a/src/dev/ci_setup/setup.sh +++ b/src/dev/ci_setup/setup.sh @@ -2,39 +2,7 @@ set -e -dir="$(pwd)" -cacheDir="${CACHE_DIR:-"$HOME/.kibana"}" - -RED='\033[0;31m' -C_RESET='\033[0m' # Reset color - -### -### Since the Jenkins logging output collector doesn't look like a TTY -### Node/Chalk and other color libs disable their color output. But Jenkins -### can handle color fine, so this forces https://github.com/chalk/supports-color -### to enable color support in Chalk and other related modules. -### -export FORCE_COLOR=1 - -### -### check that we seem to be in a kibana project -### -if [ -f "$dir/package.json" ] && [ -f "$dir/.node-version" ]; then - echo "Setting up node.js and yarn in $dir" -else - echo "${RED}src/dev/ci_setup/setup.sh must be run within a kibana repo${C_RESET}" - exit 1 -fi - - -export KIBANA_DIR="$dir" -export XPACK_DIR="$KIBANA_DIR/x-pack" - -parentDir="$(cd "$KIBANA_DIR/.."; pwd)" -export PARENT_DIR="$parentDir" - -kbnBranch="$(jq -r .branch "$KIBANA_DIR/package.json")" -export KIBANA_PKG_BRANCH="$kbnBranch" +source src/dev/ci_setup/setup_env.sh true echo " -- KIBANA_DIR='$KIBANA_DIR'" echo " -- XPACK_DIR='$XPACK_DIR'" @@ -42,76 +10,6 @@ echo " -- PARENT_DIR='$PARENT_DIR'" echo " -- KIBANA_PKG_BRANCH='$KIBANA_PKG_BRANCH'" echo " -- TEST_ES_SNAPSHOT_VERSION='$TEST_ES_SNAPSHOT_VERSION'" -### -### download node -### -UNAME=$(uname) -OS="linux" -if [[ "$UNAME" = *"MINGW64_NT"* ]]; then - OS="win" -fi -echo " -- Running on OS: $OS" - -nodeVersion="$(cat "$dir/.node-version")" -nodeDir="$cacheDir/node/$nodeVersion" - -if [[ "$OS" == "win" ]]; then - nodeBin="$HOME/node" - nodeUrl="https://nodejs.org/dist/v$nodeVersion/node-v$nodeVersion-win-x64.zip" -else - nodeBin="$nodeDir/bin" - nodeUrl="https://nodejs.org/dist/v$nodeVersion/node-v$nodeVersion-linux-x64.tar.gz" -fi - -echo " -- node: version=v${nodeVersion} dir=$nodeDir" - -echo " -- setting up node.js" -if [ -x "$nodeBin/node" ] && [ "$("$nodeBin/node" --version)" == "v$nodeVersion" ]; then - echo " -- reusing node.js install" -else - if [ -d "$nodeDir" ]; then - echo " -- clearing previous node.js install" - rm -rf "$nodeDir" - fi - - echo " -- downloading node.js from $nodeUrl" - mkdir -p "$nodeDir" - if [[ "$OS" == "win" ]]; then - nodePkg="$nodeDir/${nodeUrl##*/}" - curl --silent -o "$nodePkg" "$nodeUrl" - unzip -qo "$nodePkg" -d "$nodeDir" - mv "${nodePkg%.*}" "$nodeBin" - else - curl --silent "$nodeUrl" | tar -xz -C "$nodeDir" --strip-components=1 - fi -fi - -### -### "install" node into this shell -### -export PATH="$nodeBin:$PATH" - -### -### downloading yarn -### -yarnVersion="$(node -e "console.log(String(require('./package.json').engines.yarn || '').replace(/^[^\d]+/,''))")" -npm install -g "yarn@^${yarnVersion}" - -### -### setup yarn offline cache -### -yarn config set yarn-offline-mirror "$cacheDir/yarn-offline-cache" - -### -### "install" yarn into this shell -### -yarnGlobalDir="$(yarn global bin)" -export PATH="$PATH:$yarnGlobalDir" - -# use a proxy to fetch chromedriver/geckodriver asset -export GECKODRIVER_CDNURL="https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache" -export CHROMEDRIVER_CDNURL="https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache" - ### ### install dependencies ### @@ -159,28 +57,3 @@ if [ "$GIT_CHANGES" ]; then echo -e "$GIT_CHANGES\n" exit 1 fi - -### -### github-checks-reporter kill switch. Remove to disable -### -export CHECKS_REPORTER_ACTIVE=true - -### only run on pr jobs -if [[ "$JOB_NAME" != "elastic+kibana+pull-request"* ]] ; then - export CHECKS_REPORTER_ACTIVE=false -fi - -### -### Implements github-checks-reporter kill switch when scripts are called from the command line -### $@ - all arguments -### -function checks-reporter-with-killswitch() { - if [ "$CHECKS_REPORTER_ACTIVE" == "true" ] ; then - yarn run github-checks-reporter "$@" - else - arguments=("$@"); - "${arguments[@]:1}"; - fi -} - -export -f checks-reporter-with-killswitch diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh new file mode 100644 index 0000000000000..006a35d7035b3 --- /dev/null +++ b/src/dev/ci_setup/setup_env.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash + +set -e + +installNode=$1 + +dir="$(pwd)" +cacheDir="${CACHE_DIR:-"$HOME/.kibana"}" + +RED='\033[0;31m' +C_RESET='\033[0m' # Reset color + +### +### Since the Jenkins logging output collector doesn't look like a TTY +### Node/Chalk and other color libs disable their color output. But Jenkins +### can handle color fine, so this forces https://github.com/chalk/supports-color +### to enable color support in Chalk and other related modules. +### +export FORCE_COLOR=1 + +### +### check that we seem to be in a kibana project +### +if [ -f "$dir/package.json" ] && [ -f "$dir/.node-version" ]; then + echo "Setting up node.js and yarn in $dir" +else + echo "${RED}src/dev/ci_setup/setup.sh must be run within a kibana repo${C_RESET}" + exit 1 +fi + + +export KIBANA_DIR="$dir" +export XPACK_DIR="$KIBANA_DIR/x-pack" + +parentDir="$(cd "$KIBANA_DIR/.."; pwd)" +export PARENT_DIR="$parentDir" + +kbnBranch="$(jq -r .branch "$KIBANA_DIR/package.json")" +export KIBANA_PKG_BRANCH="$kbnBranch" + +### +### download node +### +UNAME=$(uname) +OS="linux" +if [[ "$UNAME" = *"MINGW64_NT"* ]]; then + OS="win" +fi +echo " -- Running on OS: $OS" + +nodeVersion="$(cat "$dir/.node-version")" +nodeDir="$cacheDir/node/$nodeVersion" + +if [[ "$OS" == "win" ]]; then + nodeBin="$HOME/node" + nodeUrl="https://nodejs.org/dist/v$nodeVersion/node-v$nodeVersion-win-x64.zip" +else + nodeBin="$nodeDir/bin" + nodeUrl="https://nodejs.org/dist/v$nodeVersion/node-v$nodeVersion-linux-x64.tar.gz" +fi + +if [[ "$installNode" == "true" ]]; then + echo " -- node: version=v${nodeVersion} dir=$nodeDir" + + echo " -- setting up node.js" + if [ -x "$nodeBin/node" ] && [ "$("$nodeBin/node" --version)" == "v$nodeVersion" ]; then + echo " -- reusing node.js install" + else + if [ -d "$nodeDir" ]; then + echo " -- clearing previous node.js install" + rm -rf "$nodeDir" + fi + + echo " -- downloading node.js from $nodeUrl" + mkdir -p "$nodeDir" + if [[ "$OS" == "win" ]]; then + nodePkg="$nodeDir/${nodeUrl##*/}" + curl --silent -o "$nodePkg" "$nodeUrl" + unzip -qo "$nodePkg" -d "$nodeDir" + mv "${nodePkg%.*}" "$nodeBin" + else + curl --silent "$nodeUrl" | tar -xz -C "$nodeDir" --strip-components=1 + fi + fi +fi + +### +### "install" node into this shell +### +export PATH="$nodeBin:$PATH" + +if [[ "$installNode" == "true" || ! $(which yarn) ]]; then + ### + ### downloading yarn + ### + yarnVersion="$(node -e "console.log(String(require('./package.json').engines.yarn || '').replace(/^[^\d]+/,''))")" + npm install -g "yarn@^${yarnVersion}" +fi + +### +### setup yarn offline cache +### +yarn config set yarn-offline-mirror "$cacheDir/yarn-offline-cache" + +### +### "install" yarn into this shell +### +yarnGlobalDir="$(yarn global bin)" +export PATH="$PATH:$yarnGlobalDir" + +# use a proxy to fetch chromedriver/geckodriver asset +export GECKODRIVER_CDNURL="https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache" +export CHROMEDRIVER_CDNURL="https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache" + + +export CHECKS_REPORTER_ACTIVE=false + +### only run on pr jobs for elastic/kibana, checks-reporter doesn't work for other repos +if [[ "$ghprbPullId" && "$ghprbGhRepository" == 'elastic/kibana' ]] ; then + export CHECKS_REPORTER_ACTIVE=true +fi + +### +### Implements github-checks-reporter kill switch when scripts are called from the command line +### $@ - all arguments +### +function checks-reporter-with-killswitch() { + if [ "$CHECKS_REPORTER_ACTIVE" == "true" ] ; then + yarn run github-checks-reporter "$@" + else + arguments=("$@"); + "${arguments[@]:1}"; + fi +} + +export -f checks-reporter-with-killswitch + +source "$KIBANA_DIR/src/dev/ci_setup/load_env_keys.sh" diff --git a/src/dev/ci_setup/setup_percy.sh b/src/dev/ci_setup/setup_percy.sh index c008dc1d5cdbd..ed6a15d056fe5 100755 --- a/src/dev/ci_setup/setup_percy.sh +++ b/src/dev/ci_setup/setup_percy.sh @@ -15,3 +15,5 @@ export PUPPETEER_EXECUTABLE_PATH eval "$(node ./src/dev/ci_setup/get_percy_env)" echo " -- PERCY_PARALLEL_NONCE='$PERCY_PARALLEL_NONCE'" echo " -- PERCY_PARALLEL_TOTAL='$PERCY_PARALLEL_TOTAL'" +echo " -- PERCY_BRANCH='$PERCY_BRANCH'" +echo " -- PERCY_TARGET_BRANCH='$PERCY_TARGET_BRANCH'" diff --git a/src/dev/eslint/lint_files.js b/src/dev/eslint/lint_files.js index a003db51be6ae..ac1b442200a72 100644 --- a/src/dev/eslint/lint_files.js +++ b/src/dev/eslint/lint_files.js @@ -19,7 +19,7 @@ import { CLIEngine } from 'eslint'; -import { createFailError } from '../run'; +import { createFailError } from '@kbn/dev-utils'; import { REPO_ROOT } from '../constants'; /** diff --git a/src/dev/failed_tests/cli.js b/src/dev/failed_tests/cli.js index b5d2dd78daa74..a9f031448d601 100644 --- a/src/dev/failed_tests/cli.js +++ b/src/dev/failed_tests/cli.js @@ -22,15 +22,21 @@ const { resolve } = require('path'); // force cwd process.chdir(resolve(__dirname, '../../..')); -if (!process.env.JOB_NAME) { - console.log('Unable to determine job name'); +// JOB_NAME is formatted as `elastic+kibana+7.x` in some places and `elastic+kibana+7.x/JOB=kibana-intake,node=immutable` in others + +const jobNameSplit = (process.env.JOB_NAME || '').split(/\+|\//); +const branch = jobNameSplit.length >= 3 ? jobNameSplit[2] : process.env.GIT_BRANCH; + +const isPr = !!process.env.ghprbPullId; + +if (!branch) { + console.log('Unable to determine originating branch from job name or other environment variables'); process.exit(1); } -// JOB_NAME is formatted as `elastic+kibana+7.x` in some places and `elastic+kibana+7.x/JOB=kibana-intake,node=immutable` in others -const [org, proj, branch] = process.env.JOB_NAME.split(/\+|\//); -const masterOrVersion = branch === 'master' || branch.match(/^\d+\.(x|\d+)$/); -if (!(org === 'elastic' && proj === 'kibana' && masterOrVersion)) { +const isMasterOrVersion = branch.match(/^(origin\/){0,1}master$/) || branch.match(/^(origin\/){0,1}\d+\.(x|\d+)$/); + +if (!isMasterOrVersion || isPr) { console.log('Failure issues only created on master/version branch jobs'); process.exit(0); } diff --git a/src/dev/i18n/extract_default_translations.js b/src/dev/i18n/extract_default_translations.js index a449d19bc6e87..687a833aee290 100644 --- a/src/dev/i18n/extract_default_translations.js +++ b/src/dev/i18n/extract_default_translations.js @@ -26,7 +26,7 @@ import { } from './extractors'; import { globAsync, readFileAsync, normalizePath } from './utils'; -import { createFailError, isFailError } from '../run'; +import { createFailError, isFailError } from '@kbn/dev-utils'; function addMessageToMap(targetMap, key, value, reporter) { const existingValue = targetMap.get(key); diff --git a/src/dev/i18n/extractors/code.js b/src/dev/i18n/extractors/code.js index 88d1764fa40e5..58ca059be5491 100644 --- a/src/dev/i18n/extractors/code.js +++ b/src/dev/i18n/extractors/code.js @@ -29,7 +29,7 @@ import { import { extractI18nCallMessages } from './i18n_call'; import { createParserErrorMessage, isI18nTranslateFunction, traverseNodes } from '../utils'; import { extractIntlMessages, extractFormattedMessages } from './react'; -import { createFailError, isFailError } from '../../run'; +import { createFailError, isFailError } from '@kbn/dev-utils'; /** * Detect Intl.formatMessage() function call (React). diff --git a/src/dev/i18n/extractors/html.js b/src/dev/i18n/extractors/html.js index 78f5bf6e986ea..5b45738209264 100644 --- a/src/dev/i18n/extractors/html.js +++ b/src/dev/i18n/extractors/html.js @@ -33,7 +33,7 @@ import { extractDescriptionValueFromNode, } from '../utils'; import { DEFAULT_MESSAGE_KEY, DESCRIPTION_KEY, VALUES_KEY } from '../constants'; -import { createFailError, isFailError } from '../../run'; +import { createFailError, isFailError } from '@kbn/dev-utils'; /** * Find all substrings of "{{ any text }}" pattern allowing '{' and '}' chars in single quote strings diff --git a/src/dev/i18n/extractors/i18n_call.js b/src/dev/i18n/extractors/i18n_call.js index 34c2b2971f341..118cf63ce8a30 100644 --- a/src/dev/i18n/extractors/i18n_call.js +++ b/src/dev/i18n/extractors/i18n_call.js @@ -29,7 +29,7 @@ import { extractValuesKeysFromNode, } from '../utils'; import { DEFAULT_MESSAGE_KEY, DESCRIPTION_KEY, VALUES_KEY } from '../constants'; -import { createFailError } from '../../run'; +import { createFailError } from '@kbn/dev-utils'; /** * Extract messages from `funcName('id', { defaultMessage: 'Message text' })` call expression AST diff --git a/src/dev/i18n/extractors/pug.js b/src/dev/i18n/extractors/pug.js index 82ae6dcdf5833..a19d2183af2a1 100644 --- a/src/dev/i18n/extractors/pug.js +++ b/src/dev/i18n/extractors/pug.js @@ -21,7 +21,7 @@ import { parse } from '@babel/parser'; import { extractI18nCallMessages } from './i18n_call'; import { isI18nTranslateFunction, traverseNodes, createParserErrorMessage } from '../utils'; -import { createFailError, isFailError } from '../../run'; +import { createFailError, isFailError } from '@kbn/dev-utils'; /** * Matches `i18n(...)` in `#{i18n('id', { defaultMessage: 'Message text' })}` diff --git a/src/dev/i18n/extractors/react.js b/src/dev/i18n/extractors/react.js index c05f3d9524fb2..3b0c37b20375c 100644 --- a/src/dev/i18n/extractors/react.js +++ b/src/dev/i18n/extractors/react.js @@ -30,7 +30,7 @@ import { checkValuesProperty, } from '../utils'; import { DEFAULT_MESSAGE_KEY, VALUES_KEY, DESCRIPTION_KEY } from '../constants'; -import { createFailError } from '../../run'; +import { createFailError } from '@kbn/dev-utils'; /** * Extract default messages from ReactJS intl.formatMessage(...) AST diff --git a/src/dev/i18n/integrate_locale_files.ts b/src/dev/i18n/integrate_locale_files.ts index 7ed5e788be298..0c61c6514ffd7 100644 --- a/src/dev/i18n/integrate_locale_files.ts +++ b/src/dev/i18n/integrate_locale_files.ts @@ -21,6 +21,7 @@ import { ToolingLog } from '@kbn/dev-utils'; import { i18n } from '@kbn/i18n'; import path from 'path'; +import { createFailError } from '@kbn/dev-utils'; import { accessAsync, checkValuesProperty, @@ -33,7 +34,6 @@ import { // @ts-ignore } from './utils'; -import { createFailError } from '../run'; import { I18nConfig } from './config'; import { serializeToJson } from './serializers'; diff --git a/src/dev/i18n/tasks/extract_default_translations.ts b/src/dev/i18n/tasks/extract_default_translations.ts index 3384e3c515822..8ff2bc14abafd 100644 --- a/src/dev/i18n/tasks/extract_default_translations.ts +++ b/src/dev/i18n/tasks/extract_default_translations.ts @@ -18,7 +18,7 @@ */ import chalk from 'chalk'; -import { createFailError } from '../../run'; +import { createFailError } from '@kbn/dev-utils'; import { ErrorReporter, extractMessagesFromPathToMap, filterConfigPaths, I18nConfig } from '..'; export function extractDefaultMessages(config: I18nConfig, inputPaths: string[]) { diff --git a/src/dev/i18n/tasks/extract_untracked_translations.ts b/src/dev/i18n/tasks/extract_untracked_translations.ts index 087bb59a4ecd4..05866ee1f1d2c 100644 --- a/src/dev/i18n/tasks/extract_untracked_translations.ts +++ b/src/dev/i18n/tasks/extract_untracked_translations.ts @@ -17,7 +17,7 @@ * under the License. */ -import { createFailError } from '../../run'; +import { createFailError } from '@kbn/dev-utils'; import { I18nConfig, matchEntriesWithExctractors, diff --git a/src/dev/i18n/utils.js b/src/dev/i18n/utils.js index cbaab5152bb9e..e8d7265b7fa2c 100644 --- a/src/dev/i18n/utils.js +++ b/src/dev/i18n/utils.js @@ -36,7 +36,7 @@ import path from 'path'; import chalk from 'chalk'; import parser from 'intl-messageformat-parser'; -import { createFailError } from '../run'; +import { createFailError } from '@kbn/dev-utils'; const ESCAPE_LINE_BREAK_REGEX = /(? !pattern.includes('integration_tests') diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index e694e9142126e..24c2825e28174 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -66,7 +66,7 @@ export default { setupFilesAfterEnv: [ '/src/dev/jest/setup/mocks.js', ], - coverageDirectory: '/target/jest-coverage', + coverageDirectory: '/target/kibana-coverage/jest', coverageReporters: [ 'html', 'text', diff --git a/src/dev/jest/integration_tests/junit_reporter.test.js b/src/dev/jest/integration_tests/junit_reporter.test.js index 47618ce0fe70c..b2ceedfb9f711 100644 --- a/src/dev/jest/integration_tests/junit_reporter.test.js +++ b/src/dev/jest/integration_tests/junit_reporter.test.js @@ -29,7 +29,7 @@ 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 = resolve(TARGET_DIR, 'junit/TEST-Jest Tests.xml'); +const XML_PATH = resolve(TARGET_DIR, 'junit', process.env.JOB || '.', 'TEST-Jest Tests.xml'); afterAll(async () => { await del(TARGET_DIR); diff --git a/src/dev/jest/junit_reporter.js b/src/dev/jest/junit_reporter.js index 86b780bac9bfa..3c94f5fe3719d 100644 --- a/src/dev/jest/junit_reporter.js +++ b/src/dev/jest/junit_reporter.js @@ -23,7 +23,7 @@ import { writeFileSync } from 'fs'; import mkdirp from 'mkdirp'; import xmlBuilder from 'xmlbuilder'; -import { escapeCdata } from '../xml'; +import { escapeCdata } from '@kbn/test'; const ROOT_DIR = dirname(require.resolve('../../../package.json')); @@ -33,10 +33,7 @@ const ROOT_DIR = dirname(require.resolve('../../../package.json')); */ export default class JestJUnitReporter { constructor(globalConfig, options = {}) { - const { - reportName = 'Jest Tests', - rootDirectory = ROOT_DIR - } = options; + const { reportName = 'Jest Tests', rootDirectory = ROOT_DIR } = options; this._reportName = reportName; this._rootDirectory = resolve(rootDirectory); @@ -62,8 +59,8 @@ export default class JestJUnitReporter { { skipNullAttributes: true } ); - const msToIso = ms => ms ? new Date(ms).toISOString().slice(0, -5) : undefined; - const msToSec = ms => ms ? (ms / 1000).toFixed(3) : undefined; + 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', @@ -83,7 +80,7 @@ export default class JestJUnitReporter { tests: suite.testResults.length, failures: suite.numFailingTests, skipped: suite.numPendingTests, - file: suite.testFilePath + file: suite.testFilePath, }); // nested in there are the tests in that file @@ -93,10 +90,10 @@ export default class JestJUnitReporter { const testEl = suiteEl.ele('testcase', { classname, name: [...test.ancestorTitles, test.title].join(' '), - time: msToSec(test.duration) + time: msToSec(test.duration), }); - test.failureMessages.forEach((message) => { + test.failureMessages.forEach(message => { testEl.ele('failure').dat(escapeCdata(message)); }); @@ -106,12 +103,18 @@ export default class JestJUnitReporter { }); }); - const reportPath = resolve(rootDirectory, `target/junit/TEST-${reportName}.xml`); + const reportPath = resolve( + rootDirectory, + 'target/junit', + process.env.JOB || '.', + `TEST-${reportName}.xml` + ); + const reportXML = root.end({ pretty: true, indent: ' ', newline: '\n', - spacebeforeslash: '' + spacebeforeslash: '', }); mkdirp.sync(dirname(reportPath)); diff --git a/src/dev/jest/setup/after_env.integration.js b/src/dev/jest/setup/after_env.integration.js index 7a2e7b8ab31c3..21a9545c7cf7e 100644 --- a/src/dev/jest/setup/after_env.integration.js +++ b/src/dev/jest/setup/after_env.integration.js @@ -20,6 +20,6 @@ /* eslint-env jest */ /** - * Set the default timeout for the integration test suite to 30 seconds + * Set the default timeout for the integration test suite to 10 minutes */ -jest.setTimeout(30 * 1000); +jest.setTimeout(10 * 60 * 1000); diff --git a/src/dev/jest/setup/babel_polyfill.js b/src/dev/jest/setup/babel_polyfill.js index 945d76e4be800..58325c1a67f94 100644 --- a/src/dev/jest/setup/babel_polyfill.js +++ b/src/dev/jest/setup/babel_polyfill.js @@ -21,5 +21,3 @@ // 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'; -// Required for EUI -import 'regenerator-runtime/runtime'; diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 2380207572337..4fe50baaf83be 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -94,7 +94,7 @@ export const LICENSE_OVERRIDES = { 'sha.js@2.4.11': ['BSD-3-Clause AND MIT'], // TODO can be removed if the ISSUE#239 is accepted on the source - 'xmldom@0.1.19': ['MIT'], + 'xmldom@0.1.27': ['MIT'], // TODO can be removed if the PR#9 is accepted on the source 'pause-stream@0.0.11': ['MIT'], diff --git a/src/dev/license_checker/run_check_licenses_cli.ts b/src/dev/license_checker/run_check_licenses_cli.ts index 47b1d0e6c351d..b011e8ff6ecb2 100644 --- a/src/dev/license_checker/run_check_licenses_cli.ts +++ b/src/dev/license_checker/run_check_licenses_cli.ts @@ -17,8 +17,8 @@ * under the License. */ +import { run } from '@kbn/dev-utils'; import { getInstalledPackages } from '../npm'; -import { run } from '../run'; import { LICENSE_WHITELIST, DEV_ONLY_LICENSE_WHITELIST, LICENSE_OVERRIDES } from './config'; import { assertLicensesValid } from './valid'; diff --git a/src/dev/license_checker/valid.ts b/src/dev/license_checker/valid.ts index 8c6d0453d13c0..8fe09db0a5874 100644 --- a/src/dev/license_checker/valid.ts +++ b/src/dev/license_checker/valid.ts @@ -18,7 +18,7 @@ */ import dedent from 'dedent'; -import { createFailError } from '../run'; +import { createFailError } from '@kbn/dev-utils'; interface Options { packages: Array<{ diff --git a/src/dev/mocha/__tests__/junit_report_generation.js b/src/dev/mocha/__tests__/junit_report_generation.js deleted file mode 100644 index 162431d10ae3f..0000000000000 --- a/src/dev/mocha/__tests__/junit_report_generation.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. - */ - -import { resolve } from 'path'; -import { readFileSync } from 'fs'; - -import { fromNode as fcb } from 'bluebird'; -import { parseString } from 'xml2js'; -import del from 'del'; -import Mocha from 'mocha'; -import expect from '@kbn/expect'; - -import { setupJUnitReportGeneration } from '../junit_report_generation'; - -const PROJECT_DIR = resolve(__dirname, 'fixtures/project'); -const DURATION_REGEX = /^\d+\.\d{3}$/; -const ISO_DATE_SEC_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/; - -describe('dev/mocha/junit report generation', () => { - afterEach(() => { - del.sync(resolve(PROJECT_DIR, 'target')); - }); - - it('reports on failed setup hooks', async () => { - const mocha = new Mocha({ - reporter: function Runner(runner) { - setupJUnitReportGeneration(runner, { - reportName: 'test', - rootDirectory: PROJECT_DIR, - }); - }, - }); - - mocha.addFile(resolve(PROJECT_DIR, 'test.js')); - await new Promise(resolve => mocha.run(resolve)); - const report = await fcb(cb => - parseString(readFileSync(resolve(PROJECT_DIR, 'target/junit/TEST-test.xml')), cb) - ); - - // test case results are wrapped in - expect(report).to.eql({ - testsuites: { - testsuite: [report.testsuites.testsuite[0]], - }, - }); - - // the single element at the root contains summary data for all tests results - const [testsuite] = report.testsuites.testsuite; - expect(testsuite.$.time).to.match(DURATION_REGEX); - expect(testsuite.$.timestamp).to.match(ISO_DATE_SEC_REGEX); - expect(testsuite).to.eql({ - $: { - failures: '2', - skipped: '1', - tests: '4', - time: testsuite.$.time, - timestamp: testsuite.$.timestamp, - }, - testcase: testsuite.testcase, - }); - - // there are actually only three tests, but since the hook failed - // it is reported as a test failure - expect(testsuite.testcase).to.have.length(4); - const [testPass, testFail, beforeEachFail, testSkipped] = testsuite.testcase; - - const sharedClassname = testPass.$.classname; - expect(sharedClassname).to.match(/^test\.test[^\.]js$/); - expect(testPass.$.time).to.match(DURATION_REGEX); - expect(testPass).to.eql({ - $: { - classname: sharedClassname, - name: 'SUITE works', - time: testPass.$.time, - }, - 'system-out': testPass['system-out'], - }); - - expect(testFail.$.time).to.match(DURATION_REGEX); - expect(testFail.failure[0]).to.match(/Error: FORCE_TEST_FAIL\n.+fixtures.project.test.js/); - expect(testFail).to.eql({ - $: { - classname: sharedClassname, - name: 'SUITE fails', - time: testFail.$.time, - }, - 'system-out': testFail['system-out'], - failure: [testFail.failure[0]], - }); - - expect(beforeEachFail.$.time).to.match(DURATION_REGEX); - expect(beforeEachFail.failure).to.have.length(1); - expect(beforeEachFail.failure[0]).to.match( - /Error: FORCE_HOOK_FAIL\n.+fixtures.project.test.js/ - ); - expect(beforeEachFail).to.eql({ - $: { - classname: sharedClassname, - name: 'SUITE SUB_SUITE "before each" hook: fail hook for "never runs"', - time: beforeEachFail.$.time, - }, - 'system-out': testFail['system-out'], - failure: [beforeEachFail.failure[0]], - }); - - expect(testSkipped).to.eql({ - $: { - classname: sharedClassname, - name: 'SUITE SUB_SUITE never runs', - }, - 'system-out': testFail['system-out'], - skipped: [''], - }); - }); -}); diff --git a/src/dev/mocha/index.js b/src/dev/mocha/index.js deleted file mode 100644 index 9f99f56831263..0000000000000 --- a/src/dev/mocha/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 { createAutoJUnitReporter } from './auto_junit_reporter'; -export { setupJUnitReportGeneration } from './junit_report_generation'; -export { runMochaCli } from './run_mocha_cli'; diff --git a/src/dev/mocha/junit_report_generation.js b/src/dev/mocha/junit_report_generation.js deleted file mode 100644 index 2efac9cf12e3c..0000000000000 --- a/src/dev/mocha/junit_report_generation.js +++ /dev/null @@ -1,150 +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 } from 'fs'; -import { inspect } from 'util'; - -import mkdirp from 'mkdirp'; -import xmlBuilder from 'xmlbuilder'; - -import { getSnapshotOfRunnableLogs } from './log_cache'; -import { escapeCdata } from '../xml'; - -const dateNow = Date.now.bind(Date); - -export function setupJUnitReportGeneration(runner, options = {}) { - const { - reportName = 'Unnamed Mocha Tests', - rootDirectory = dirname(require.resolve('../../../package.json')), - } = options; - - const stats = {}; - const results = []; - - const getDuration = node => - node.startTime && node.endTime ? ((node.endTime - node.startTime) / 1000).toFixed(3) : null; - - const findAllTests = suite => - suite.suites.reduce((acc, suite) => acc.concat(findAllTests(suite)), suite.tests); - - const setStartTime = node => { - node.startTime = dateNow(); - }; - - const setEndTime = node => { - node.endTime = dateNow(); - }; - - const getFullTitle = node => { - const parentTitle = node.parent && getFullTitle(node.parent); - return parentTitle ? `${parentTitle} ${node.title}` : node.title; - }; - - const getPath = node => { - if (node.file) { - return relative(rootDirectory, node.file); - } - - if (node.parent) { - return getPath(node.parent); - } - - return 'unknown'; - }; - - runner.on('start', () => setStartTime(stats)); - runner.on('suite', setStartTime); - runner.on('hook', setStartTime); - runner.on('hook end', setEndTime); - runner.on('test', setStartTime); - runner.on('pass', node => results.push({ node })); - runner.on('pass', setEndTime); - runner.on('fail', (node, error) => results.push({ failed: true, error, node })); - runner.on('fail', setEndTime); - runner.on('suite end', () => setEndTime(stats)); - - runner.on('end', () => { - // crawl the test graph to collect all defined tests - const allTests = findAllTests(runner.suite); - if (!allTests.length) { - return; - } - - // filter out just the failures - const failures = results.filter(result => result.failed); - - // any failure that isn't for a test is for a hook - const failedHooks = failures.filter(result => !allTests.includes(result.node)); - - // mocha doesn't emit 'pass' or 'fail' when it skips a test - // or a test is pending, so we find them ourselves - const skippedResults = allTests - .filter(node => node.pending || !results.find(result => result.node === node)) - .map(node => ({ skipped: true, node })); - - const builder = xmlBuilder.create( - 'testsuites', - { encoding: 'utf-8' }, - {}, - { skipNullAttributes: true } - ); - - const testsuitesEl = builder.ele('testsuite', { - timestamp: new Date(stats.startTime).toISOString().slice(0, -5), - time: getDuration(stats), - tests: allTests.length + failedHooks.length, - failures: failures.length, - skipped: skippedResults.length, - }); - - function addTestcaseEl(node) { - return testsuitesEl.ele('testcase', { - name: getFullTitle(node), - classname: `${reportName}.${getPath(node).replace(/\./g, '·')}`, - time: getDuration(node), - }); - } - - [...results, ...skippedResults].forEach(result => { - const el = addTestcaseEl(result.node); - el.ele('system-out').dat(escapeCdata(getSnapshotOfRunnableLogs(result.node) || '')); - - if (result.failed) { - el.ele('failure').dat(escapeCdata(inspect(result.error))); - return; - } - - if (result.skipped) { - el.ele('skipped'); - } - }); - - const reportPath = resolve(rootDirectory, `target/junit/TEST-${reportName}.xml`); - const reportXML = builder.end({ - pretty: true, - indent: ' ', - newline: '\n', - spacebeforeslash: '', - }); - - mkdirp.sync(dirname(reportPath)); - writeFileSync(reportPath, reportXML, 'utf8'); - }); -} diff --git a/src/dev/notice/generate_notice_from_source.js b/src/dev/notice/generate_notice_from_source.js index ba1492b9d8260..75bc7c8cb2f19 100644 --- a/src/dev/notice/generate_notice_from_source.js +++ b/src/dev/notice/generate_notice_from_source.js @@ -42,9 +42,9 @@ export async function generateNoticeFromSource({ productName, directory, log }) cwd: directory, nodir: true, ignore: [ - '{node_modules,build,target,dist,optimize,built_assets}/**', + '{node_modules,build,target,dist,data,built_assets}/**', 'packages/*/{node_modules,build,target,dist}/**', - 'x-pack/{node_modules,build,target,dist,optimize}/**', + 'x-pack/{node_modules,build,target,dist,data}/**', 'x-pack/packages/*/{node_modules,build,target,dist}/**', ] }; diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index f5de9c815cc43..b50b00f54350b 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -43,6 +43,8 @@ export const IGNORE_FILE_GLOBS = [ 'x-pack/docs/**/*', 'src/legacy/ui/public/assets/fonts/**/*', 'packages/kbn-utility-types/test-d/**/*', + 'Jenkinsfile', + 'Dockerfile*', // Files in this directory must match a pre-determined name in some cases. 'x-pack/legacy/plugins/canvas/.storybook/*', diff --git a/src/dev/precommit_hook/check_file_casing.js b/src/dev/precommit_hook/check_file_casing.js index d4781bb78ecf3..2580d6e0655c8 100644 --- a/src/dev/precommit_hook/check_file_casing.js +++ b/src/dev/precommit_hook/check_file_casing.js @@ -21,7 +21,7 @@ import { relative, basename } from 'path'; import { dim } from 'chalk'; -import { createFailError } from '../run'; +import { createFailError } from '@kbn/dev-utils'; import { matchesAnyGlob } from '../globs'; import { diff --git a/src/dev/prs/github_api.ts b/src/dev/prs/github_api.ts index c0a4a03897775..c14b848ae63bc 100644 --- a/src/dev/prs/github_api.ts +++ b/src/dev/prs/github_api.ts @@ -19,7 +19,7 @@ import axios, { AxiosError, AxiosResponse } from 'axios'; -import { createFailError } from '../run'; +import { createFailError } from '@kbn/dev-utils'; interface ResponseError extends AxiosError { request: any; diff --git a/src/dev/prs/pr.ts b/src/dev/prs/pr.ts index 7b86b1229e83f..18476cf225bdc 100644 --- a/src/dev/prs/pr.ts +++ b/src/dev/prs/pr.ts @@ -17,7 +17,7 @@ * under the License. */ -import { createFlagError } from '../run'; +import { createFlagError } from '@kbn/dev-utils'; const isNum = (input: string) => { return /^\d+$/.test(input); diff --git a/src/dev/prs/run_update_prs_cli.ts b/src/dev/prs/run_update_prs_cli.ts index e626dcee6d340..6d99ac5fa45f3 100644 --- a/src/dev/prs/run_update_prs_cli.ts +++ b/src/dev/prs/run_update_prs_cli.ts @@ -25,8 +25,8 @@ import chalk from 'chalk'; import { first, tap } from 'rxjs/operators'; import dedent from 'dedent'; +import { run, createFlagError } from '@kbn/dev-utils'; import { getLine$ } from './helpers'; -import { run, createFlagError } from '../run'; import { Pr } from './pr'; import { GithubApi } from './github_api'; diff --git a/src/dev/renovate/config.ts b/src/dev/renovate/config.ts index 9abf5842df8cd..a86c080f52710 100644 --- a/src/dev/renovate/config.ts +++ b/src/dev/renovate/config.ts @@ -21,7 +21,7 @@ import { RENOVATE_PACKAGE_GROUPS } from './package_groups'; import { PACKAGE_GLOBS } from './package_globs'; import { wordRegExp, maybeFlatMap, maybeMap, getTypePackageName } from './utils'; -const DEFAULT_LABELS = ['release_note:skip', 'renovate', 'v8.0.0', 'v7.3.0']; +const DEFAULT_LABELS = ['release_note:skip', 'renovate', 'v8.0.0', 'v7.5.0']; export const RENOVATE_CONFIG = { extends: ['config:base'], @@ -63,9 +63,9 @@ export const RENOVATE_CONFIG = { /** * Policy for how to modify/update existing ranges - * pin = convert ranges to exact versions, e.g. ^1.0.0 -> 1.1.0 + * bump = e.g. bump the range even if the new version satisifies the existing range, e.g. ^1.0.0 -> ^1.1.0 */ - rangeStrategy: 'replace', + rangeStrategy: 'bump', npm: { /** @@ -98,8 +98,9 @@ export const RENOVATE_CONFIG = { /** * Limit the number of active PRs renovate will allow + * 0 (default) means no limit */ - prConcurrentLimit: 6, + prConcurrentLimit: 0, /** * Disable vulnerability alert handling, we handle that separately diff --git a/src/dev/renovate/package_groups.ts b/src/dev/renovate/package_groups.ts index 05f8823c7b3e6..cc7157bee6cd1 100644 --- a/src/dev/renovate/package_groups.ts +++ b/src/dev/renovate/package_groups.ts @@ -113,7 +113,7 @@ export const RENOVATE_PACKAGE_GROUPS: PackageGroup[] = [ { name: 'graphql', - packageWords: ['graphql'], + packageWords: ['graphql', 'apollo'], }, { @@ -125,6 +125,7 @@ export const RENOVATE_PACKAGE_GROUPS: PackageGroup[] = [ { name: 'vega', packageWords: ['vega'], + enabled: false, }, { @@ -155,6 +156,11 @@ export const RENOVATE_PACKAGE_GROUPS: PackageGroup[] = [ packageNames: ['jsts'], allowedVersions: '^1.6.2', }, + + { + name: 'storybook', + packageWords: ['storybook'], + }, ]; /** diff --git a/src/dev/renovate/run_build_renovate_config_cli.ts b/src/dev/renovate/run_build_renovate_config_cli.ts index 699b6f155adcb..db08bbc8a8f23 100644 --- a/src/dev/renovate/run_build_renovate_config_cli.ts +++ b/src/dev/renovate/run_build_renovate_config_cli.ts @@ -22,7 +22,7 @@ import { resolve } from 'path'; import json5 from 'json5'; import dedent from 'dedent'; -import { run } from '../run'; +import { run } from '@kbn/dev-utils'; import { REPO_ROOT } from '../constants'; import { RENOVATE_CONFIG } from './config'; diff --git a/src/dev/run/README.md b/src/dev/run/README.md deleted file mode 100644 index a7f46c8a03a76..0000000000000 --- a/src/dev/run/README.md +++ /dev/null @@ -1,133 +0,0 @@ -# dev/run - -Helper functions for writing little scripts for random build/ci/dev tasks. - -## Usage - -Define the function that should validate the CLI arguments and call your task fn: - -```ts -// dev/my_task/run_my_task.ts -import { createFlagError, run } from '../run'; - -run( - async ({ flags, log }) => { - if (typeof flags.path !== 'string') { - throw createFlagError('please provide a single --path flag'); - } - - await runTask(flags.path); - log.success('task complete'); - }, - { - description: ` - Run my special task - `, - flags: { - string: ['path'], - help: ` - --path Required, path to the file to operate on - ` - }, - } -); -``` - -Define the script which will setup node and load the script source: - -```js -// scripts/my_task.js - -require('../src/setup_node_env'); -require('../src/dev/my_task/run_my_task'); -``` - -Try out the script: - -```sh -$ node scripts/my_task - -# ERROR please provide a single --path flag -# -# node scripts/my_task.js -# -# Run my special task -# -# Options: -# --path Required, path to the file to operate on -# --verbose, -v Log verbosely -# --debug Log debug messages (less than verbose) -# --quiet Only log errors -# --silent Don't log anything -# --help Show this message -# -``` - -## API - -- ***`run(fn: async ({ flags: Flags, log: ToolingLog, addCleanupTask }) => Promise, options: Options)`*** - - Execte an async function, passing it the parsed flags and a tooling log that is configured to the requested logging level. If the returned promise is rejected with an error created by `createFailError(...)` or `createFlagError(...)` the process will exit as described by the error, otherwise the process will exit with code 1. - - **`fn` Params:** - - *[`log: ToolingLog`](../../../packages/kbn-dev-utils/src/tooling_log/tooling_log.js)*: - - An instance of the `ToolingLog` that is configured with the standard flags: `--verbose`, `--quiet`, `--silent`, and `--debug` - - - *[`flags: Flags`](flags.ts)*: - - The parsed CLI flags, created by [`getopts`](https://www.npmjs.com/package/getopts). Includes the default flags for controlling the log level of the ToolingLog, and `flags.unexpected`, which is an array of flag names which were passed but not expected. - - - *`addCleanupTask: (task: CleanupTask) => void`*: - - A function that registers a task to be called __once__ as soon as one of the following occurs: - - 1. `fn` resolve/rejects - 2. something calls `process.exit()` - 3. the user hits ctrl+c in their terminal causing the SIGINT signal to be sent to the process - - **`Options`:** - - *`usage: string`* - - A bit of text to replace the default usage in the `--help` text. - - - *`description: string`* - - A bit of text to replace the default description in the `--help` text. - - - *`flags.help: string`* - - A bit of text included at the top of the `Options:` section of the `--help` text. - - - *`flags.string: string[]`* - - An array of flag names that are expected to have a string value. - - - *`flags.boolean: string[]`* - - An array of flag names that are expected to have a boolean value. - - - *`flags.alias: { [short: string], string }`* - - A map of short flag names to long flag names, used to expand short flags like `-v` to `--verbose`. - - - *`flags.default: { [name: string]: string | string[] | boolean | undefined }`* - - A map of flag names to their default value. If the flag is not defined this value will be set in the flags object passed to the run `fn`. - - - *`flags.allowUnexpected: boolean`* - - By default, any flag that is passed but not mentioned in `flags.string`, `flags.boolean`, `flags.alias` or `flags.default` will trigger an error, preventing the run function from calling its first argument. If you have a reason to disable this behavior set this option to `true`. - - -- ***`createFailError(reason: string, options: { exitCode: number, showHelp: boolean }): FailError`*** - - Create and return an error object that, when thrown within `run(...)` can customize the failure behavior of the CLI. `reason` is printed instead of a stacktrace, `options.exitCode` customizes the exit code of the process, and `options.showHelp` will print the help text before exiting. - -- ***`createFlagError(reason: string)`*** - - Shortcut for calling `createFailError()` with `options.showHelp`, as errors caused by invalid flags should print the help message to help users debug their usage. - -- ***`isFailError(error: any)`*** - - Determine if a value is an error created by `createFailError(...)`. \ No newline at end of file diff --git a/src/dev/run/index.ts b/src/dev/run/index.ts deleted file mode 100644 index 9d81ff0c9af3b..0000000000000 --- a/src/dev/run/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 { run } from './run'; -export { createFailError, createFlagError, combineErrors, isFailError } from './fail'; diff --git a/src/dev/run_check_file_casing.js b/src/dev/run_check_file_casing.js index 4b6dc48313ec4..6594a03f0db12 100644 --- a/src/dev/run_check_file_casing.js +++ b/src/dev/run_check_file_casing.js @@ -19,7 +19,7 @@ import globby from 'globby'; -import { run } from './run'; +import { run } from '@kbn/dev-utils'; import { File } from './file'; import { REPO_ROOT } from './constants'; import { checkFileCasing } from './precommit_hook/check_file_casing'; diff --git a/src/dev/run_i18n_check.ts b/src/dev/run_i18n_check.ts index d3c98a02edfe1..f686c18c848f2 100644 --- a/src/dev/run_i18n_check.ts +++ b/src/dev/run_i18n_check.ts @@ -20,6 +20,7 @@ import chalk from 'chalk'; import Listr from 'listr'; +import { createFailError, run } from '@kbn/dev-utils'; import { ErrorReporter, I18nConfig } from './i18n'; import { extractDefaultMessages, @@ -28,7 +29,6 @@ import { checkConfigs, mergeConfigs, } from './i18n/tasks'; -import { createFailError, run } from './run'; const skipNoTranslations = ({ config }: { config: I18nConfig }) => !config.translations.length; diff --git a/src/dev/run_i18n_extract.ts b/src/dev/run_i18n_extract.ts index 7026d9e14ebba..5492b5cd6795c 100644 --- a/src/dev/run_i18n_extract.ts +++ b/src/dev/run_i18n_extract.ts @@ -21,9 +21,9 @@ import chalk from 'chalk'; import Listr from 'listr'; import { resolve } from 'path'; +import { createFailError, run } from '@kbn/dev-utils'; import { ErrorReporter, serializeToJson, serializeToJson5, writeFileAsync } from './i18n'; import { extractDefaultMessages, mergeConfigs } from './i18n/tasks'; -import { createFailError, run } from './run'; run( async ({ @@ -88,6 +88,7 @@ run( log.error(error); } } + process.exit(); }, { flags: { diff --git a/src/dev/run_i18n_integrate.ts b/src/dev/run_i18n_integrate.ts index 9b006fd9b3972..1b23725a653d7 100644 --- a/src/dev/run_i18n_integrate.ts +++ b/src/dev/run_i18n_integrate.ts @@ -20,9 +20,9 @@ import chalk from 'chalk'; import Listr from 'listr'; +import { createFailError, run } from '@kbn/dev-utils'; import { ErrorReporter, integrateLocaleFiles } from './i18n'; import { extractDefaultMessages, mergeConfigs } from './i18n/tasks'; -import { createFailError, run } from './run'; run( async ({ diff --git a/src/dev/run_precommit_hook.js b/src/dev/run_precommit_hook.js index 14526ba98b28e..4e5f8d9c5b1c0 100644 --- a/src/dev/run_precommit_hook.js +++ b/src/dev/run_precommit_hook.js @@ -17,7 +17,7 @@ * under the License. */ -import { run, combineErrors } from './run'; +import { run, combineErrors } from '@kbn/dev-utils'; import * as Eslint from './eslint'; import * as Sasslint from './sasslint'; import { getFilesForCommit, checkFileCasing } from './precommit_hook'; diff --git a/src/dev/run_register_git_hook.js b/src/dev/run_register_git_hook.js index ffa6552f4ff1f..8d5bb9e59359b 100644 --- a/src/dev/run_register_git_hook.js +++ b/src/dev/run_register_git_hook.js @@ -17,7 +17,7 @@ * under the License. */ -import { run, createFailError } from './run'; +import { run, createFailError } from '@kbn/dev-utils'; import { registerPrecommitGitHook } from './register_git_hook'; run(async ({ log }) => { diff --git a/src/dev/sass/build_sass.js b/src/dev/sass/build_sass.js index 51d6454ac45fb..14f03a7a116a6 100644 --- a/src/dev/sass/build_sass.js +++ b/src/dev/sass/build_sass.js @@ -21,7 +21,7 @@ import { resolve } from 'path'; import { toArray } from 'rxjs/operators'; -import { createFailError } from '../run'; +import { createFailError } from '@kbn/dev-utils'; import { findPluginSpecs } from '../../legacy/plugin_discovery'; import { collectUiExports } from '../../legacy/ui'; import { buildAll } from '../../legacy/server/sass/build_all'; diff --git a/src/dev/sass/run_build_sass_cli.js b/src/dev/sass/run_build_sass_cli.js index e5e6d076a947a..439d16178c417 100644 --- a/src/dev/sass/run_build_sass_cli.js +++ b/src/dev/sass/run_build_sass_cli.js @@ -17,7 +17,7 @@ * under the License. */ -import { run } from '../run'; +import { run } from '@kbn/dev-utils'; import { REPO_ROOT } from '../constants'; import { buildSass } from './build_sass'; diff --git a/src/dev/sasslint/lint_files.js b/src/dev/sasslint/lint_files.js index 098bbd0a7ec61..147560a90e71a 100644 --- a/src/dev/sasslint/lint_files.js +++ b/src/dev/sasslint/lint_files.js @@ -19,7 +19,7 @@ import sassLint from 'sass-lint'; import path from 'path'; -import { createFailError } from '../run'; +import { createFailError } from '@kbn/dev-utils'; /** * Lints a list of files with eslint. eslint reports are written to the log diff --git a/src/dev/typescript/run_check_ts_projects_cli.ts b/src/dev/typescript/run_check_ts_projects_cli.ts index d4a4b5dee5fa3..f42a4e2759370 100644 --- a/src/dev/typescript/run_check_ts_projects_cli.ts +++ b/src/dev/typescript/run_check_ts_projects_cli.ts @@ -21,7 +21,7 @@ import { resolve } from 'path'; import execa from 'execa'; -import { run } from '../run'; +import { run } from '@kbn/dev-utils'; const REPO_ROOT = resolve(__dirname, '../../../'); import { File } from '../file'; diff --git a/src/es_archiver/lib/indices/kibana_index.js b/src/es_archiver/lib/indices/kibana_index.js index 335e2acf23933..b751ca2f1864b 100644 --- a/src/es_archiver/lib/indices/kibana_index.js +++ b/src/es_archiver/lib/indices/kibana_index.js @@ -138,20 +138,30 @@ export async function cleanKibanaIndices({ client, stats, log, kibanaPluginIds } }); } - await client.deleteByQuery({ - index: `.kibana`, - body: { - query: { - bool: { - must_not: { - ids: { - values: ['space:default'], + while (true) { + const resp = await client.deleteByQuery({ + index: `.kibana`, + body: { + query: { + bool: { + must_not: { + ids: { + values: ['space:default'], + }, }, }, }, }, - }, - }); + ignore: [409] + }); + + if (resp.total !== resp.deleted) { + log.warning('delete by query deleted %d of %d total documents, trying again', resp.deleted, resp.total); + continue; + } + + break; + } log.warning( `since spaces are enabled, all objects other than the default space were deleted from ` + diff --git a/src/fixtures/stubbed_logstash_index_pattern.js b/src/fixtures/stubbed_logstash_index_pattern.js index 88dc5d708dc5f..dd0381c440bd6 100644 --- a/src/fixtures/stubbed_logstash_index_pattern.js +++ b/src/fixtures/stubbed_logstash_index_pattern.js @@ -40,7 +40,7 @@ export default function stubbedLogstashIndexPatternService(Private) { }; }); - const indexPattern = new StubIndexPattern('logstash-*', 'time', fields); + const indexPattern = new StubIndexPattern('logstash-*', cfg => cfg, 'time', fields); indexPattern.id = 'logstash-*'; return indexPattern; diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.help.json b/src/legacy/core_plugins/console/api_server/spec/generated/cat.help.json deleted file mode 100644 index b58aea9e3f0d5..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.help.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "cat.help": { - "url_params": { - "help": "__flag__", - "s": [] - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cat" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.master.json b/src/legacy/core_plugins/console/api_server/spec/generated/cat.master.json deleted file mode 100644 index f81936af95856..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.master.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "cat.master": { - "url_params": { - "format": "", - "local": "__flag__", - "master_timeout": "", - "h": [], - "help": "__flag__", - "s": [], - "v": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cat/master" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-master.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.nodeattrs.json b/src/legacy/core_plugins/console/api_server/spec/generated/cat.nodeattrs.json deleted file mode 100644 index 711f2be480fd4..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.nodeattrs.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "cat.nodeattrs": { - "url_params": { - "format": "", - "local": "__flag__", - "master_timeout": "", - "h": [], - "help": "__flag__", - "s": [], - "v": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cat/nodeattrs" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-nodeattrs.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.pending_tasks.json b/src/legacy/core_plugins/console/api_server/spec/generated/cat.pending_tasks.json deleted file mode 100644 index ef694ec382701..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.pending_tasks.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "cat.pending_tasks": { - "url_params": { - "format": "", - "local": "__flag__", - "master_timeout": "", - "h": [], - "help": "__flag__", - "s": [], - "v": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cat/pending_tasks" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-pending-tasks.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.plugins.json b/src/legacy/core_plugins/console/api_server/spec/generated/cat.plugins.json deleted file mode 100644 index 4b5c8fce2fdf9..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.plugins.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "cat.plugins": { - "url_params": { - "format": "", - "local": "__flag__", - "master_timeout": "", - "h": [], - "help": "__flag__", - "s": [], - "v": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cat/plugins" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-plugins.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.repositories.json b/src/legacy/core_plugins/console/api_server/spec/generated/cat.repositories.json deleted file mode 100644 index 3aad8a5ee518f..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.repositories.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "cat.repositories": { - "url_params": { - "format": "", - "local": "__flag__", - "master_timeout": "", - "h": [], - "help": "__flag__", - "s": [], - "v": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cat/repositories" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-repositories.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/clear_scroll.json b/src/legacy/core_plugins/console/api_server/spec/generated/clear_scroll.json deleted file mode 100644 index f7a42c291b7b4..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/clear_scroll.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "clear_scroll": { - "methods": [ - "DELETE" - ], - "patterns": [ - "_search/scroll" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-scroll.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.allocation_explain.json b/src/legacy/core_plugins/console/api_server/spec/generated/cluster.allocation_explain.json deleted file mode 100644 index a44eb2e117a78..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.allocation_explain.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "cluster.allocation_explain": { - "url_params": { - "include_yes_decisions": "__flag__", - "include_disk_info": "__flag__" - }, - "methods": [ - "GET", - "POST" - ], - "patterns": [ - "_cluster/allocation/explain" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-allocation-explain.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.get_settings.json b/src/legacy/core_plugins/console/api_server/spec/generated/cluster.get_settings.json deleted file mode 100644 index 998e9a953ec9a..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.get_settings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "cluster.get_settings": { - "url_params": { - "flat_settings": "__flag__", - "master_timeout": "", - "timeout": "", - "include_defaults": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cluster/settings" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.pending_tasks.json b/src/legacy/core_plugins/console/api_server/spec/generated/cluster.pending_tasks.json deleted file mode 100644 index 0883bf50db2e5..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.pending_tasks.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "cluster.pending_tasks": { - "url_params": { - "local": "__flag__", - "master_timeout": "" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cluster/pending_tasks" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-pending.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.put_settings.json b/src/legacy/core_plugins/console/api_server/spec/generated/cluster.put_settings.json deleted file mode 100644 index 1ce70f64ff0fc..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.put_settings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "cluster.put_settings": { - "url_params": { - "flat_settings": "__flag__", - "master_timeout": "", - "timeout": "" - }, - "methods": [ - "PUT" - ], - "patterns": [ - "_cluster/settings" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.remote_info.json b/src/legacy/core_plugins/console/api_server/spec/generated/cluster.remote_info.json deleted file mode 100644 index e7f612eb2adc9..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.remote_info.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "cluster.remote_info": { - "methods": [ - "GET" - ], - "patterns": [ - "_remote/info" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-remote-info.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.reroute.json b/src/legacy/core_plugins/console/api_server/spec/generated/cluster.reroute.json deleted file mode 100644 index 627e1c1335bf4..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.reroute.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "cluster.reroute": { - "url_params": { - "dry_run": "__flag__", - "explain": "__flag__", - "retry_failed": "__flag__", - "metric": [], - "master_timeout": "", - "timeout": "" - }, - "methods": [ - "POST" - ], - "patterns": [ - "_cluster/reroute" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-reroute.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.stats.json b/src/legacy/core_plugins/console/api_server/spec/generated/cluster.stats.json deleted file mode 100644 index 96bf4fb98941c..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.stats.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "cluster.stats": { - "url_params": { - "flat_settings": "__flag__", - "timeout": "" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_cluster/stats", - "_cluster/stats/nodes/{nodes}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-stats.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/create.json b/src/legacy/core_plugins/console/api_server/spec/generated/create.json deleted file mode 100644 index 94209e5685e4f..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/create.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "create": { - "url_params": { - "wait_for_active_shards": "", - "refresh": [ - "true", - "false", - "wait_for" - ], - "routing": "", - "timeout": "", - "version": "", - "version_type": [ - "internal", - "external", - "external_gte", - "force" - ], - "pipeline": "" - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "{indices}/_create/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/delete.json b/src/legacy/core_plugins/console/api_server/spec/generated/delete.json deleted file mode 100644 index 367f1147ede42..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/delete.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "delete": { - "url_params": { - "wait_for_active_shards": "", - "refresh": [ - "true", - "false", - "wait_for" - ], - "routing": "", - "timeout": "", - "if_seq_no": "", - "if_primary_term": "", - "version": "", - "version_type": [ - "internal", - "external", - "external_gte", - "force" - ] - }, - "methods": [ - "DELETE" - ], - "patterns": [ - "{indices}/_doc/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-delete.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/delete_script.json b/src/legacy/core_plugins/console/api_server/spec/generated/delete_script.json deleted file mode 100644 index e99354c737960..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/delete_script.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "delete_script": { - "url_params": { - "timeout": "", - "master_timeout": "" - }, - "methods": [ - "DELETE" - ], - "patterns": [ - "_scripts/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/exists.json b/src/legacy/core_plugins/console/api_server/spec/generated/exists.json deleted file mode 100644 index 0a2eb775f629e..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/exists.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "exists": { - "url_params": { - "stored_fields": [], - "preference": "random", - "realtime": "__flag__", - "refresh": "__flag__", - "routing": "", - "_source": [], - "_source_excludes": [], - "_source_includes": [], - "version": "", - "version_type": [ - "internal", - "external", - "external_gte", - "force" - ] - }, - "methods": [ - "HEAD" - ], - "patterns": [ - "{indices}/_doc/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/exists_source.json b/src/legacy/core_plugins/console/api_server/spec/generated/exists_source.json deleted file mode 100644 index 6d5be39a7c892..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/exists_source.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "exists_source": { - "url_params": { - "preference": "random", - "realtime": "__flag__", - "refresh": "__flag__", - "routing": "", - "_source": [], - "_source_excludes": [], - "_source_includes": [], - "version": "", - "version_type": [ - "internal", - "external", - "external_gte", - "force" - ] - }, - "methods": [ - "HEAD" - ], - "patterns": [ - "{indices}/_source/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/explain.json b/src/legacy/core_plugins/console/api_server/spec/generated/explain.json deleted file mode 100644 index ecbc5c80ee814..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/explain.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "explain": { - "url_params": { - "analyze_wildcard": "__flag__", - "analyzer": "", - "default_operator": [ - "AND", - "OR" - ], - "df": "_all", - "stored_fields": [], - "lenient": "__flag__", - "preference": "random", - "q": "", - "routing": "", - "_source": [], - "_source_excludes": [], - "_source_includes": [] - }, - "methods": [ - "GET", - "POST" - ], - "patterns": [ - "{indices}/_explain/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-explain.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/get.json b/src/legacy/core_plugins/console/api_server/spec/generated/get.json deleted file mode 100644 index 48d9cd8727c43..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/get.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "get": { - "url_params": { - "stored_fields": [], - "preference": "random", - "realtime": "__flag__", - "refresh": "__flag__", - "routing": "", - "_source": [], - "_source_excludes": [], - "_source_includes": [], - "version": "", - "version_type": [ - "internal", - "external", - "external_gte", - "force" - ] - }, - "methods": [ - "GET" - ], - "patterns": [ - "{indices}/_doc/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/get_script.json b/src/legacy/core_plugins/console/api_server/spec/generated/get_script.json deleted file mode 100644 index f0c3e809cf17b..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/get_script.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "get_script": { - "url_params": { - "master_timeout": "" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_scripts/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/get_source.json b/src/legacy/core_plugins/console/api_server/spec/generated/get_source.json deleted file mode 100644 index 9c69234014862..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/get_source.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "get_source": { - "url_params": { - "preference": "random", - "realtime": "__flag__", - "refresh": "__flag__", - "routing": "", - "_source": [], - "_source_excludes": [], - "_source_includes": [], - "version": "", - "version_type": [ - "internal", - "external", - "external_gte", - "force" - ] - }, - "methods": [ - "GET" - ], - "patterns": [ - "{indices}/_source/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.analyze.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.analyze.json deleted file mode 100644 index f808cbf7c3a12..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.analyze.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "indices.analyze": { - "url_params": { - "index": "" - }, - "methods": [ - "GET", - "POST" - ], - "patterns": [ - "_analyze", - "{indices}/_analyze" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-analyze.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.create.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.create.json deleted file mode 100644 index 28c38e5f8ccb2..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.create.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "indices.create": { - "url_params": { - "include_type_name": "__flag__", - "wait_for_active_shards": "", - "timeout": "", - "master_timeout": "" - }, - "methods": [ - "PUT" - ], - "patterns": [ - "{indices}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-create-index.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete_alias.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete_alias.json deleted file mode 100644 index e055dcd9ab78a..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete_alias.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "indices.delete_alias": { - "url_params": { - "timeout": "", - "master_timeout": "" - }, - "methods": [ - "DELETE" - ], - "patterns": [ - "{indices}/_alias/{name}", - "{indices}/_aliases/{name}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete_template.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete_template.json deleted file mode 100644 index d215c42b06bd7..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete_template.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "indices.delete_template": { - "url_params": { - "timeout": "", - "master_timeout": "" - }, - "methods": [ - "DELETE" - ], - "patterns": [ - "_template/{name}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_template.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_template.json deleted file mode 100644 index 7c74deaa74bdd..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_template.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "indices.exists_template": { - "url_params": { - "flat_settings": "__flag__", - "master_timeout": "", - "local": "__flag__" - }, - "methods": [ - "HEAD" - ], - "patterns": [ - "_template/{name}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_field_mapping.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_field_mapping.json deleted file mode 100644 index f8b1b23914470..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_field_mapping.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "indices.get_field_mapping": { - "url_params": { - "include_type_name": "__flag__", - "include_defaults": "__flag__", - "ignore_unavailable": "__flag__", - "allow_no_indices": "__flag__", - "expand_wildcards": [ - "open", - "closed", - "none", - "all" - ], - "local": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_mapping/field/{fields}", - "{indices}/_mapping/field/{fields}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-field-mapping.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_mapping.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_mapping.json deleted file mode 100644 index 8150369f1bc11..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_mapping.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "indices.get_mapping": { - "url_params": { - "include_type_name": "__flag__", - "ignore_unavailable": "__flag__", - "allow_no_indices": "__flag__", - "expand_wildcards": [ - "open", - "closed", - "none", - "all" - ], - "master_timeout": "", - "local": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_mapping", - "{indices}/_mapping" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-mapping.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_template.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_template.json deleted file mode 100644 index 5ce052354a79d..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_template.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "indices.get_template": { - "url_params": { - "include_type_name": "__flag__", - "flat_settings": "__flag__", - "master_timeout": "", - "local": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_template", - "_template/{name}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_alias.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_alias.json deleted file mode 100644 index 51151bd1238b3..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_alias.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "indices.put_alias": { - "url_params": { - "timeout": "", - "master_timeout": "" - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "{indices}/_alias/{name}", - "{indices}/_aliases/{name}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_mapping.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_mapping.json deleted file mode 100644 index 3568add1500f9..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_mapping.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "indices.put_mapping": { - "url_params": { - "include_type_name": "__flag__", - "timeout": "", - "master_timeout": "", - "ignore_unavailable": "__flag__", - "allow_no_indices": "__flag__", - "expand_wildcards": [ - "open", - "closed", - "none", - "all" - ] - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "{indices}/_mapping" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-put-mapping.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.recovery.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.recovery.json deleted file mode 100644 index 2e869f065002b..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.recovery.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "indices.recovery": { - "url_params": { - "detailed": "__flag__", - "active_only": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_recovery", - "{indices}/_recovery" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-recovery.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.rollover.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.rollover.json deleted file mode 100644 index 4a1723b4e1861..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.rollover.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "indices.rollover": { - "url_params": { - "include_type_name": "__flag__", - "timeout": "", - "dry_run": "__flag__", - "master_timeout": "", - "wait_for_active_shards": "" - }, - "methods": [ - "POST" - ], - "patterns": [ - "{alias}/_rollover", - "{alias}/_rollover/{new_index}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-rollover-index.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.shrink.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.shrink.json deleted file mode 100644 index 60978da9e5663..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.shrink.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "indices.shrink": { - "url_params": { - "timeout": "", - "master_timeout": "", - "wait_for_active_shards": "" - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "{indices}/_shrink/{target}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shrink-index.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.split.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.split.json deleted file mode 100644 index 265ed882a2f4b..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.split.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "indices.split": { - "url_params": { - "timeout": "", - "master_timeout": "", - "wait_for_active_shards": "" - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "{indices}/_split/{target}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-split-index.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.update_aliases.json b/src/legacy/core_plugins/console/api_server/spec/generated/indices.update_aliases.json deleted file mode 100644 index 066efa7b1c4fd..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.update_aliases.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "indices.update_aliases": { - "url_params": { - "timeout": "", - "master_timeout": "" - }, - "methods": [ - "POST" - ], - "patterns": [ - "_aliases" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/info.json b/src/legacy/core_plugins/console/api_server/spec/generated/info.json deleted file mode 100644 index 4a70e6124afec..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/info.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "info": { - "methods": [ - "GET" - ], - "patterns": [ - "" - ], - "documentation": "http://www.elastic.co/guide/" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/mget.json b/src/legacy/core_plugins/console/api_server/spec/generated/mget.json deleted file mode 100644 index 45d9330dc387f..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/mget.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "mget": { - "url_params": { - "stored_fields": [], - "preference": "random", - "realtime": "__flag__", - "refresh": "__flag__", - "routing": "", - "_source": [], - "_source_excludes": [], - "_source_includes": [] - }, - "methods": [ - "GET", - "POST" - ], - "patterns": [ - "_mget", - "{indices}/_mget" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-get.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.hot_threads.json b/src/legacy/core_plugins/console/api_server/spec/generated/nodes.hot_threads.json deleted file mode 100644 index 672dbafd7b91f..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.hot_threads.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "nodes.hot_threads": { - "url_params": { - "interval": "", - "snapshots": "10", - "threads": "3", - "ignore_idle_threads": "__flag__", - "type": [ - "cpu", - "wait", - "block" - ], - "timeout": "" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_nodes/hot_threads", - "_nodes/{nodes}/hot_threads" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-hot-threads.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.usage.json b/src/legacy/core_plugins/console/api_server/spec/generated/nodes.usage.json deleted file mode 100644 index ac280632721d7..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.usage.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "nodes.usage": { - "url_params": { - "timeout": "" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_nodes/usage", - "_nodes/{nodes}/usage", - "_nodes/usage/{metrics}", - "_nodes/{nodes}/usage/{metrics}" - ], - "url_components": { - "metrics": [ - "_all", - "rest_actions" - ], - "nodes": null - }, - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-usage.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/ping.json b/src/legacy/core_plugins/console/api_server/spec/generated/ping.json deleted file mode 100644 index 88c83ece5882c..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/ping.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ping": { - "methods": [ - "HEAD" - ], - "patterns": [ - "" - ], - "documentation": "http://www.elastic.co/guide/" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/put_script.json b/src/legacy/core_plugins/console/api_server/spec/generated/put_script.json deleted file mode 100644 index d386a2709c99f..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/put_script.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "put_script": { - "url_params": { - "timeout": "", - "master_timeout": "", - "context": "" - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "_scripts/{id}", - "_scripts/{id}/{context}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/scroll.json b/src/legacy/core_plugins/console/api_server/spec/generated/scroll.json deleted file mode 100644 index 03ab7557323f5..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/scroll.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "scroll": { - "url_params": { - "scroll": "", - "scroll_id": "", - "rest_total_hits_as_int": "__flag__" - }, - "methods": [ - "GET", - "POST" - ], - "patterns": [ - "_search/scroll" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-scroll.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.create.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.create.json deleted file mode 100644 index 6670a1f2f39d9..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.create.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "snapshot.create": { - "url_params": { - "master_timeout": "", - "wait_for_completion": "__flag__" - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "_snapshot/{repository}/{snapshot}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.create_repository.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.create_repository.json deleted file mode 100644 index 180724c1495fc..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.create_repository.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "snapshot.create_repository": { - "url_params": { - "master_timeout": "", - "timeout": "", - "verify": "__flag__" - }, - "methods": [ - "PUT", - "POST" - ], - "patterns": [ - "_snapshot/{repository}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.delete.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.delete.json deleted file mode 100644 index 2600179997e77..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.delete.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "snapshot.delete": { - "url_params": { - "master_timeout": "" - }, - "methods": [ - "DELETE" - ], - "patterns": [ - "_snapshot/{repository}/{snapshot}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.delete_repository.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.delete_repository.json deleted file mode 100644 index 0b613b7677fa0..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.delete_repository.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "snapshot.delete_repository": { - "url_params": { - "master_timeout": "", - "timeout": "" - }, - "methods": [ - "DELETE" - ], - "patterns": [ - "_snapshot/{repository}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.get.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.get.json deleted file mode 100644 index 29975fd72d651..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.get.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "snapshot.get": { - "url_params": { - "master_timeout": "", - "ignore_unavailable": "__flag__", - "verbose": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_snapshot/{repository}/{snapshot}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.get_repository.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.get_repository.json deleted file mode 100644 index 7d6e5b683c1c5..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.get_repository.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "snapshot.get_repository": { - "url_params": { - "master_timeout": "", - "local": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_snapshot", - "_snapshot/{repository}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.restore.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.restore.json deleted file mode 100644 index 130d3f51594a9..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.restore.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "snapshot.restore": { - "url_params": { - "master_timeout": "", - "wait_for_completion": "__flag__" - }, - "methods": [ - "POST" - ], - "patterns": [ - "_snapshot/{repository}/{snapshot}/_restore" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.status.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.status.json deleted file mode 100644 index 1e0ea8c1f6d7e..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.status.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "snapshot.status": { - "url_params": { - "master_timeout": "", - "ignore_unavailable": "__flag__" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_snapshot/_status", - "_snapshot/{repository}/_status", - "_snapshot/{repository}/{snapshot}/_status" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.verify_repository.json b/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.verify_repository.json deleted file mode 100644 index a1e8bef616395..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/snapshot.verify_repository.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "snapshot.verify_repository": { - "url_params": { - "master_timeout": "", - "timeout": "" - }, - "methods": [ - "POST" - ], - "patterns": [ - "_snapshot/{repository}/_verify" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/tasks.cancel.json b/src/legacy/core_plugins/console/api_server/spec/generated/tasks.cancel.json deleted file mode 100644 index 42a8daeae8e39..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/tasks.cancel.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "tasks.cancel": { - "url_params": { - "nodes": [], - "actions": [], - "parent_task_id": "" - }, - "methods": [ - "POST" - ], - "patterns": [ - "_tasks/_cancel", - "_tasks/{task_id}/_cancel" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/tasks.get.json b/src/legacy/core_plugins/console/api_server/spec/generated/tasks.get.json deleted file mode 100644 index 92230d0ace495..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/tasks.get.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "tasks.get": { - "url_params": { - "wait_for_completion": "__flag__", - "timeout": "" - }, - "methods": [ - "GET" - ], - "patterns": [ - "_tasks/{task_id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" - } -} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/update.json b/src/legacy/core_plugins/console/api_server/spec/generated/update.json deleted file mode 100644 index 09e4acfa2d851..0000000000000 --- a/src/legacy/core_plugins/console/api_server/spec/generated/update.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "update": { - "url_params": { - "wait_for_active_shards": "", - "_source": [], - "_source_excludes": [], - "_source_includes": [], - "lang": "painless", - "refresh": [ - "true", - "false", - "wait_for" - ], - "retry_on_conflict": "0", - "routing": "", - "timeout": "", - "if_seq_no": "", - "if_primary_term": "" - }, - "methods": [ - "POST" - ], - "patterns": [ - "{indices}/_update/{id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update.html" - } -} diff --git a/src/legacy/core_plugins/console/index.js b/src/legacy/core_plugins/console/index.js deleted file mode 100644 index 8c5da496afc21..0000000000000 --- a/src/legacy/core_plugins/console/index.js +++ /dev/null @@ -1,175 +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 Boom from 'boom'; -import { first } from 'rxjs/operators'; -import { resolve, join, sep } from 'path'; -import url from 'url'; -import { has, isEmpty, head, pick } from 'lodash'; - -import { resolveApi } from './api_server/server'; -import { addExtensionSpecFilePath } from './api_server/spec'; -import { setHeaders } from './server/set_headers'; - -import { - ProxyConfigCollection, - getElasticsearchProxyConfig, - createProxyRoute -} from './server'; - -function filterHeaders(originalHeaders, headersToKeep) { - const normalizeHeader = function (header) { - if (!header) { - return ''; - } - header = header.toString(); - return header.trim().toLowerCase(); - }; - - // Normalize list of headers we want to allow in upstream request - const headersToKeepNormalized = headersToKeep.map(normalizeHeader); - - return pick(originalHeaders, headersToKeepNormalized); -} - -export default function (kibana) { - const modules = resolve(__dirname, 'public/webpackShims/'); - const src = resolve(__dirname, 'public/src/'); - - let defaultVars; - const apps = []; - return new kibana.Plugin({ - id: 'console', - require: ['elasticsearch'], - - config: function (Joi) { - return Joi.object({ - enabled: Joi.boolean().default(true), - proxyFilter: Joi.array().items(Joi.string()).single().default(['.*']), - ssl: Joi.object({ - verify: Joi.boolean(), - }).default(), - proxyConfig: Joi.array().items( - Joi.object().keys({ - match: Joi.object().keys({ - protocol: Joi.string().default('*'), - host: Joi.string().default('*'), - port: Joi.string().default('*'), - path: Joi.string().default('*') - }), - - timeout: Joi.number(), - ssl: Joi.object().keys({ - verify: Joi.boolean(), - ca: Joi.array().single().items(Joi.string()), - cert: Joi.string(), - key: Joi.string() - }).default() - }) - ).default() - }).default(); - }, - - deprecations: function () { - return [ - (settings, log) => { - if (has(settings, 'proxyConfig')) { - log('Config key "proxyConfig" is deprecated. Configuration can be inferred from the "elasticsearch" settings'); - } - } - ]; - }, - - uiCapabilities() { - return { - dev_tools: { - show: true, - save: true, - }, - }; - }, - - async init(server, options) { - server.expose('addExtensionSpecFilePath', addExtensionSpecFilePath); - if (options.ssl && options.ssl.verify) { - throw new Error('sense.ssl.verify is no longer supported.'); - } - - const config = server.config(); - const legacyEsConfig = await server.newPlatform.setup.core.elasticsearch.legacy.config$.pipe(first()).toPromise(); - const proxyConfigCollection = new ProxyConfigCollection(options.proxyConfig); - const proxyPathFilters = options.proxyFilter.map(str => new RegExp(str)); - - defaultVars = { - elasticsearchUrl: url.format( - Object.assign(url.parse(head(legacyEsConfig.hosts)), { auth: false }) - ), - }; - - server.route(createProxyRoute({ - baseUrl: head(legacyEsConfig.hosts), - pathFilters: proxyPathFilters, - getConfigForReq(req, uri) { - const filteredHeaders = filterHeaders(req.headers, legacyEsConfig.requestHeadersWhitelist); - const headers = setHeaders(filteredHeaders, legacyEsConfig.customHeaders); - - if (!isEmpty(config.get('console.proxyConfig'))) { - return { - ...proxyConfigCollection.configForUri(uri), - headers, - }; - } - - return { - ...getElasticsearchProxyConfig(legacyEsConfig), - headers, - }; - } - })); - - server.route({ - path: '/api/console/api_server', - method: ['GET', 'POST'], - handler: function (req, h) { - const { sense_version: version, apis } = req.query; - if (!apis) { - throw Boom.badRequest('"apis" is a required param.'); - } - - return resolveApi(version, apis.split(','), h); - } - }); - }, - - uiExports: { - apps: apps, - hacks: ['plugins/console/hacks/register'], - devTools: ['plugins/console/console'], - styleSheetPaths: resolve(__dirname, 'public/index.scss'), - - injectDefaultVars: () => defaultVars, - - noParse: [ - join(modules, 'ace' + sep), - join(modules, 'moment_src/moment' + sep), - join(src, 'sense_editor/mode/worker.js') - ] - } - }); -} diff --git a/src/legacy/core_plugins/console/index.ts b/src/legacy/core_plugins/console/index.ts new file mode 100644 index 0000000000000..2d0ba9bc14383 --- /dev/null +++ b/src/legacy/core_plugins/console/index.ts @@ -0,0 +1,194 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Boom from 'boom'; +import { first } from 'rxjs/operators'; +import { resolve, join, sep } from 'path'; +import url from 'url'; +import { has, isEmpty, head, pick } from 'lodash'; + +// @ts-ignore +import { resolveApi } from './server/api_server/server'; +// @ts-ignore +import { addExtensionSpecFilePath } from './server/api_server/spec'; +// @ts-ignore +import { setHeaders } from './server/set_headers'; +// @ts-ignore +import { ProxyConfigCollection, getElasticsearchProxyConfig, createProxyRoute } from './server'; + +function filterHeaders(originalHeaders: any, headersToKeep: any) { + const normalizeHeader = function(header: any) { + if (!header) { + return ''; + } + header = header.toString(); + return header.trim().toLowerCase(); + }; + + // Normalize list of headers we want to allow in upstream request + const headersToKeepNormalized = headersToKeep.map(normalizeHeader); + + return pick(originalHeaders, headersToKeepNormalized); +} + +// eslint-disable-next-line +export default function(kibana: any) { + const modules = resolve(__dirname, 'public/webpackShims/'); + const quarantinedSrc = resolve(__dirname, 'public/quarantined/src/'); + const npSrc = resolve(__dirname, 'np_ready/public'); + + let defaultVars: any; + const apps: any[] = []; + return new kibana.Plugin({ + id: 'console', + require: ['elasticsearch'], + + config(Joi: any) { + return Joi.object({ + enabled: Joi.boolean().default(true), + proxyFilter: Joi.array() + .items(Joi.string()) + .single() + .default(['.*']), + ssl: Joi.object({ + verify: Joi.boolean(), + }).default(), + proxyConfig: Joi.array() + .items( + Joi.object().keys({ + match: Joi.object().keys({ + protocol: Joi.string().default('*'), + host: Joi.string().default('*'), + port: Joi.string().default('*'), + path: Joi.string().default('*'), + }), + + timeout: Joi.number(), + ssl: Joi.object() + .keys({ + verify: Joi.boolean(), + ca: Joi.array() + .single() + .items(Joi.string()), + cert: Joi.string(), + key: Joi.string(), + }) + .default(), + }) + ) + .default(), + }).default(); + }, + + deprecations() { + return [ + (settings: any, log: any) => { + if (has(settings, 'proxyConfig')) { + log( + 'Config key "proxyConfig" is deprecated. Configuration can be inferred from the "elasticsearch" settings' + ); + } + }, + ]; + }, + + uiCapabilities() { + return { + dev_tools: { + show: true, + save: true, + }, + }; + }, + + async init(server: any, options: any) { + server.expose('addExtensionSpecFilePath', addExtensionSpecFilePath); + if (options.ssl && options.ssl.verify) { + throw new Error('sense.ssl.verify is no longer supported.'); + } + + const config = server.config(); + const legacyEsConfig = await server.newPlatform.setup.core.elasticsearch.legacy.config$ + .pipe(first()) + .toPromise(); + const proxyConfigCollection = new ProxyConfigCollection(options.proxyConfig); + const proxyPathFilters = options.proxyFilter.map((str: string) => new RegExp(str)); + + defaultVars = { + elasticsearchUrl: url.format( + Object.assign(url.parse(head(legacyEsConfig.hosts)), { auth: false }) + ), + }; + + server.route( + createProxyRoute({ + baseUrl: head(legacyEsConfig.hosts), + pathFilters: proxyPathFilters, + getConfigForReq(req: any, uri: any) { + const filteredHeaders = filterHeaders( + req.headers, + legacyEsConfig.requestHeadersWhitelist + ); + const headers = setHeaders(filteredHeaders, legacyEsConfig.customHeaders); + + if (!isEmpty(config.get('console.proxyConfig'))) { + return { + ...proxyConfigCollection.configForUri(uri), + headers, + }; + } + + return { + ...getElasticsearchProxyConfig(legacyEsConfig), + headers, + }; + }, + }) + ); + + server.route({ + path: '/api/console/api_server', + method: ['GET', 'POST'], + handler(req: any, h: any) { + const { sense_version: version, apis } = req.query; + if (!apis) { + throw Boom.badRequest('"apis" is a required param.'); + } + + return resolveApi(version, apis.split(','), h); + }, + }); + }, + + uiExports: { + apps, + hacks: ['plugins/console/quarantined/hacks/register'], + devTools: [`${npSrc}/legacy`], + styleSheetPaths: resolve(__dirname, 'public/quarantined/index.scss'), + + injectDefaultVars: () => defaultVars, + + noParse: [ + join(modules, 'ace' + sep), + join(modules, 'moment_src/moment' + sep), + join(quarantinedSrc, 'sense_editor/mode/worker.js'), + ], + }, + } as any); +} diff --git a/src/legacy/core_plugins/console/np_ready/kibana.json b/src/legacy/core_plugins/console/np_ready/kibana.json new file mode 100644 index 0000000000000..ed8e4d8f15830 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/kibana.json @@ -0,0 +1,6 @@ +{ + "id": "console", + "version": "kibana", + "server": true, + "ui": true +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/console_menu.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/console_menu.tsx new file mode 100644 index 0000000000000..1fb23ffbc8897 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/console_menu.tsx @@ -0,0 +1,158 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, { Component } from 'react'; + +import { EuiButtonIcon, EuiContextMenuPanel, EuiContextMenuItem, EuiPopover } from '@elastic/eui'; + +import { FormattedMessage } from '@kbn/i18n/react'; + +interface Props { + getCurl: (cb: (text: string) => void) => void; + getDocumentation: () => Promise; + autoIndent: (ev: React.MouseEvent) => void; +} + +interface State { + isPopoverOpen: boolean; + curlCode: string; +} + +export class ConsoleMenu extends Component { + constructor(props: Props) { + super(props); + + this.state = { + curlCode: '', + isPopoverOpen: false, + }; + } + + mouseEnter = () => { + if (this.state.isPopoverOpen) return; + this.props.getCurl(text => { + this.setState({ curlCode: text }); + }); + }; + + copyAsCurl() { + this.copyText(this.state.curlCode); + } + + copyText(text: string) { + const textField = document.createElement('textarea'); + textField.innerText = text; + document.body.appendChild(textField); + textField.select(); + document.execCommand('copy'); + textField.remove(); + } + + onButtonClick = () => { + this.setState(prevState => ({ + isPopoverOpen: !prevState.isPopoverOpen, + })); + }; + + closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + }; + + openDocs = async () => { + this.closePopover(); + const documentation = await this.props.getDocumentation(); + if (!documentation) { + return; + } + window.open(documentation, '_blank'); + }; + + // Using `any` here per this issue: https://github.com/elastic/eui/issues/2265 + autoIndent: any = (event: React.MouseEvent) => { + this.closePopover(); + this.props.autoIndent(event); + }; + + render() { + const button = ( + + } + /> + ); + + const items = [ + { + this.closePopover(); + this.copyAsCurl(); + }} + > + + , + { + this.openDocs(); + }} + > + + , + + + , + ]; + + return ( + + + + + + ); + } +} diff --git a/src/legacy/core_plugins/console/public/src/components/editor_example.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/editor_example.tsx similarity index 90% rename from src/legacy/core_plugins/console/public/src/components/editor_example.tsx rename to src/legacy/core_plugins/console/np_ready/public/application/components/editor_example.tsx index 99309d7b8549c..33cefd9b20968 100644 --- a/src/legacy/core_plugins/console/public/src/components/editor_example.tsx +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/editor_example.tsx @@ -19,10 +19,10 @@ import React, { useEffect } from 'react'; // @ts-ignore -import exampleText from 'raw-loader!./help_example.txt'; +import exampleText from 'raw-loader!../constants/help_example.txt'; import $ from 'jquery'; // @ts-ignore -import SenseEditor from '../sense_editor/editor'; +import SenseEditor from '../../../../public/quarantined/src/sense_editor/editor'; interface EditorExampleProps { panel: string; diff --git a/src/legacy/core_plugins/console/public/src/components/help_panel.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/help_panel.tsx similarity index 100% rename from src/legacy/core_plugins/console/public/src/components/help_panel.tsx rename to src/legacy/core_plugins/console/np_ready/public/application/components/help_panel.tsx diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/components/index.ts new file mode 100644 index 0000000000000..0f109e99b0b39 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/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. + */ + +export * from './split_panel'; +export { TopNavMenuItem, TopNavMenu } from './top_nav_menu'; +export { ConsoleMenu } from './console_menu'; +export { WelcomePanel } from './welcome_panel'; +export { AutocompleteOptions, DevToolsSettingsModal } from './settings_modal'; +export { HelpPanel } from './help_panel'; diff --git a/src/legacy/core_plugins/console/public/src/components/settings_modal.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/settings_modal.tsx similarity index 97% rename from src/legacy/core_plugins/console/public/src/components/settings_modal.tsx rename to src/legacy/core_plugins/console/np_ready/public/application/components/settings_modal.tsx index f3ec577e43b71..9ecfc1bc4d446 100644 --- a/src/legacy/core_plugins/console/public/src/components/settings_modal.tsx +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/settings_modal.tsx @@ -35,7 +35,8 @@ import { EuiOverlayMask, EuiSwitch, } from '@elastic/eui'; -import { DevToolsSettings } from './dev_tools_settings'; + +import { DevToolsSettings } from '../../services'; export type AutocompleteOptions = 'fields' | 'indices' | 'templates'; @@ -145,11 +146,9 @@ export function DevToolsSettingsModal(props: Props) { onClick={() => { // Only refresh the currently selected settings. props.refreshAutocompleteSettings({ - autocomplete: { - fields, - indices, - templates, - }, + fields, + indices, + templates, }); }} > diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/__snapshots__/split_panel.test.tsx.snap b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/__snapshots__/split_panel.test.tsx.snap new file mode 100644 index 0000000000000..0a40e3e84211d --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/__snapshots__/split_panel.test.tsx.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Split panel should render correctly 1`] = ` + + +

+ +
+

+ A +

+
+
+ +
+ ︙ +
+
+ +
+

+ B +

+
+
+
+ + +`; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/components/resizer.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/components/resizer.tsx new file mode 100644 index 0000000000000..9d7738ac6a5a9 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/components/resizer.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 React from 'react'; + +type ResizerMouseEvent = React.MouseEvent; + +export interface Props { + onMouseDown: (eve: ResizerMouseEvent) => void; +} + +/** + * TODO: This component uses styling constants from public UI - should be removed, next iteration should incl. horizontal and vertical resizers. + */ +export function Resizer(props: Props) { + return ( +
+ ︙ +
+ ); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/containers/panel.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/containers/panel.tsx new file mode 100644 index 0000000000000..747c21433f8ed --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/containers/panel.tsx @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, { CSSProperties, ReactNode, useEffect, useRef, useState } from 'react'; +import { usePanelContext } from '../context'; + +export interface Props { + children: ReactNode[] | ReactNode; + initialWidth?: string; + style?: CSSProperties; +} + +export function Panel({ children, initialWidth = '100%', style = {} }: Props) { + const [width, setWidth] = useState(initialWidth); + const { registry } = usePanelContext(); + const divRef = useRef(null); + + useEffect(() => { + registry.registerPanel({ + initialWidth, + setWidth(value) { + setWidth(value + '%'); + }, + getWidth() { + return divRef.current!.getBoundingClientRect().width; + }, + }); + }, []); + + return ( +
+ {children} +
+ ); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/containers/panel_container.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/containers/panel_container.tsx new file mode 100644 index 0000000000000..fef65a954bd60 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/containers/panel_container.tsx @@ -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 React, { Children, ReactNode, useRef, useState } from 'react'; + +import { PanelContextProvider } from '../context'; +import { Resizer } from '../components/resizer'; +import { PanelRegistry } from '../registry'; + +export interface Props { + children: ReactNode; + onPanelWidthChange?: (arrayOfPanelWidths: number[]) => any; +} + +interface State { + isDragging: boolean; + currentResizerPos: number; +} + +const initialState: State = { isDragging: false, currentResizerPos: -1 }; + +const pxToPercent = (proportion: number, whole: number) => (proportion / whole) * 100; + +export function PanelsContainer({ children, onPanelWidthChange }: Props) { + const [firstChild, secondChild] = Children.toArray(children); + + const registryRef = useRef(new PanelRegistry()); + const containerRef = useRef(null); + const [state, setState] = useState(initialState); + + const getContainerWidth = () => { + return containerRef.current!.getBoundingClientRect().width; + }; + + const childrenWithResizer = [ + firstChild, + { + event.preventDefault(); + setState({ + ...state, + isDragging: true, + currentResizerPos: event.clientX, + }); + }} + />, + secondChild, + ]; + + return ( + +
{ + if (state.isDragging) { + const { clientX: x } = event; + const { current: registry } = registryRef; + const [left, right] = registry.getPanels(); + const delta = x - state.currentResizerPos; + const containerWidth = getContainerWidth(); + const leftPercent = pxToPercent(left.getWidth() + delta, containerWidth); + const rightPercent = pxToPercent(right.getWidth() - delta, containerWidth); + left.setWidth(leftPercent); + right.setWidth(rightPercent); + + if (onPanelWidthChange) { + onPanelWidthChange([leftPercent, rightPercent]); + } + + setState({ ...state, currentResizerPos: x }); + } + }} + onMouseUp={() => { + setState(initialState); + }} + > + {childrenWithResizer} +
+
+ ); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/context.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/context.tsx new file mode 100644 index 0000000000000..22cfee8720b9d --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/context.tsx @@ -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 React, { createContext, useContext } from 'react'; +import { PanelRegistry } from './registry'; + +const PanelContext = createContext({ registry: new PanelRegistry() }); + +interface ContextProps { + children: any; + registry: PanelRegistry; +} + +export function PanelContextProvider({ children, registry }: ContextProps) { + return {children}; +} + +export const usePanelContext = () => { + const context = useContext(PanelContext); + if (context === undefined) { + throw new Error('usePanelContext must be used within a '); + } + return context; +}; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/index.ts new file mode 100644 index 0000000000000..ed66cb958ea77 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/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 { Panel } from './containers/panel'; +export { PanelsContainer } from './containers/panel_container'; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/registry.ts b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/registry.ts new file mode 100644 index 0000000000000..5f06ab8915270 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/registry.ts @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface PanelController { + setWidth: (percent: number) => void; + getWidth: () => number; + initialWidth: string; +} + +export class PanelRegistry { + private panels: PanelController[] = []; + + registerPanel(panel: PanelController) { + this.panels.push(panel); + } + + getResizerNeighbours(idx: number) { + return [this.panels[idx], this.panels[idx + 1]]; + } + + getPanels() { + return this.panels.map(panel => ({ ...panel })); + } +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/split_panel.test.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/split_panel.test.tsx new file mode 100644 index 0000000000000..e60912a29355b --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/split_panel/split_panel.test.tsx @@ -0,0 +1,86 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { mount } from 'enzyme'; +import toJson from 'enzyme-to-json'; +import { spy } from 'sinon'; + +import { PanelsContainer, Panel } from '.'; + +const testComponentA =

A

; +const testComponentB =

B

; + +describe('Split panel', () => { + it('should render correctly', () => { + const panelContainer = mount( + + {testComponentA} + {testComponentB} + + ); + expect(toJson(panelContainer)).toMatchSnapshot(); + }); + + it('should calculate sizes correctly on mouse drags', () => { + // Since this test is not running in the browser we can't expect all of the + // APIs for sizing to be available. The below is a very hacky way of setting + // the DOMElement width so that we have a lightweight test for width calculation + // logic. + const div = mount(
); + const proto = (div + .find('div') + .first() + .getDOMNode() as any).__proto__; + const originalGetBoundingClientRect = proto.getBoundingClientRect; + + proto.getBoundingClientRect = spy(() => { + return { + width: 1000, + }; + }); + + try { + // Everything here runs sync. + let widthsCache: number[] = []; + const onWidthChange = (widths: number[]) => { + widthsCache = widths; + }; + + const panelContainer = mount( + + {testComponentA} + {testComponentB} + + ); + + const resizer = panelContainer.find(`[data-test-subj~="splitPanelResizer"]`).first(); + + resizer.simulate('mousedown', { clientX: 0 }); + resizer.simulate('mousemove', { clientX: 250 }); + resizer.simulate('mouseup'); + + panelContainer.update(); + + expect(widthsCache).toEqual([125, 75]); + } finally { + proto.getBoundingClientRect = originalGetBoundingClientRect; + } + }); +}); diff --git a/src/legacy/core_plugins/console/np_ready/public/application/components/top_nav_menu.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/top_nav_menu.tsx new file mode 100644 index 0000000000000..c83237c52febd --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/components/top_nav_menu.tsx @@ -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 React from 'react'; +import { EuiTabs, EuiTab } from '@elastic/eui'; + +export interface TopNavMenuItem { + id: string; + label: string; + description: string; + onClick: () => void; + testId: string; +} + +interface Props { + items: TopNavMenuItem[]; +} + +export function TopNavMenu({ items }: Props) { + return ( + + {items.map((item, idx) => { + return ( + + {item.label} + + ); + })} + + ); +} diff --git a/src/legacy/core_plugins/console/public/src/components/welcome_panel.tsx b/src/legacy/core_plugins/console/np_ready/public/application/components/welcome_panel.tsx similarity index 100% rename from src/legacy/core_plugins/console/public/src/components/welcome_panel.tsx rename to src/legacy/core_plugins/console/np_ready/public/application/components/welcome_panel.tsx diff --git a/src/legacy/core_plugins/console/public/src/components/help_example.txt b/src/legacy/core_plugins/console/np_ready/public/application/constants/help_example.txt similarity index 100% rename from src/legacy/core_plugins/console/public/src/components/help_example.txt rename to src/legacy/core_plugins/console/np_ready/public/application/constants/help_example.txt diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/index.ts new file mode 100644 index 0000000000000..346b748e1be91 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/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 { Editor, EditorOutput, ConsoleHistory, autoIndent, getDocumentation } from './legacy'; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/editor.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/editor.tsx new file mode 100644 index 0000000000000..0ce3d44caccd9 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/editor.tsx @@ -0,0 +1,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. + */ + +import React, { CSSProperties, useEffect, useRef, useState } from 'react'; +import { EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import $ from 'jquery'; + +import { EuiIcon } from '@elastic/eui'; +import { useAppContext } from '../../../../context'; +import { useUIAceKeyboardMode } from '../use_ui_ace_keyboard_mode'; +import { ConsoleMenu } from '../../../../components'; +import { autoIndent, getDocumentation } from '../console_menu_actions'; +import { registerCommands } from './keyboard_shortcuts'; + +// @ts-ignore +import { initializeInput } from '../../../../../../../public/quarantined/src/input'; + +export interface EditorProps { + onEditorReady?: (editor: any) => void; + sendCurrentRequest?: () => void; + docLinkVersion: string; +} + +const abs: CSSProperties = { + position: 'absolute', + top: '0', + left: '0', + bottom: '0', + right: '0', +}; + +function Component({ onEditorReady, docLinkVersion, sendCurrentRequest = () => {} }: EditorProps) { + const { + services: { history, settings }, + } = useAppContext(); + + const editorRef = useRef(null); + const actionsRef = useRef(null); + const editorInstanceRef = useRef(null); + + const [textArea, setTextArea] = useState(null); + useUIAceKeyboardMode(textArea); + + const openDocumentation = async () => { + const documentation = await getDocumentation(editorInstanceRef.current!, docLinkVersion); + if (!documentation) { + return; + } + window.open(documentation, '_blank'); + }; + + useEffect(() => { + const $editor = $(editorRef.current!); + const $actions = $(actionsRef.current!); + editorInstanceRef.current = initializeInput($editor, $actions, history, settings); + if (onEditorReady) { + onEditorReady({ editor: editorInstanceRef.current, element: editorRef.current! }); + } + + setTextArea(editorRef.current!.querySelector('textarea')); + }, []); + + useEffect(() => { + registerCommands({ + input: editorInstanceRef.current, + sendCurrentRequestToES: sendCurrentRequest, + openDocumentation, + }); + }, [sendCurrentRequest]); + + return ( +
+
+
    +
    + + + + { + editorInstanceRef.current!.getRequestsAsCURL(cb); + }} + getDocumentation={() => { + return getDocumentation(editorInstanceRef.current!, docLinkVersion); + }} + autoIndent={(event: any) => { + autoIndent(editorInstanceRef.current!, event); + }} + /> +
    +
    +
    +
+ ); +} + +export const Editor = React.memo(Component); diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/editor_output.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/editor_output.tsx new file mode 100644 index 0000000000000..94e9162d46b03 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/editor_output.tsx @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, useRef } from 'react'; +import $ from 'jquery'; + +// @ts-ignore +import { initializeOutput } from '../../../../../../../public/quarantined/src/output'; +import { useAppContext } from '../../../../context'; + +export interface EditorOutputProps { + onReady?: (ref: any) => void; +} + +function Component({ onReady }: EditorOutputProps) { + const editorRef = useRef(null); + const { + services: { settings }, + } = useAppContext(); + + useEffect(() => { + const editor$ = $(editorRef.current!); + const outputEditor = initializeOutput(editor$, settings); + if (onReady) { + onReady({ editor: outputEditor, element: editorRef.current! }); + } + }); + + return ( +
+
+
+ ); +} + +export const EditorOutput = React.memo(Component); diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/index.ts new file mode 100644 index 0000000000000..a8c603e87e7cc --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/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 { Editor } from './editor'; +export { EditorOutput } from './editor_output'; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/keyboard_shortcuts.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/keyboard_shortcuts.ts new file mode 100644 index 0000000000000..be1826afd7827 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/keyboard_shortcuts.ts @@ -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. + */ + +interface Actions { + input: any; + sendCurrentRequestToES: () => void; + openDocumentation: () => void; +} + +export function registerCommands({ input, sendCurrentRequestToES, openDocumentation }: Actions) { + input.commands.addCommand({ + name: 'send to elasticsearch', + bindKey: { win: 'Ctrl-Enter', mac: 'Command-Enter' }, + exec: () => sendCurrentRequestToES(), + }); + input.commands.addCommand({ + name: 'open documentation', + bindKey: { win: 'Ctrl-/', mac: 'Command-/' }, + exec: () => { + openDocumentation(); + }, + }); + input.commands.addCommand({ + name: 'auto indent request', + bindKey: { win: 'Ctrl-I', mac: 'Command-I' }, + exec: () => { + input.autoIndent(); + }, + }); + input.commands.addCommand({ + name: 'move to previous request start or end', + bindKey: { win: 'Ctrl-Up', mac: 'Command-Up' }, + exec: () => { + input.moveToPreviousRequestEdge(); + }, + }); + input.commands.addCommand({ + name: 'move to next request start or end', + bindKey: { win: 'Ctrl-Down', mac: 'Command-Down' }, + exec: () => { + input.moveToNextRequestEdge(); + }, + }); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/console_history.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/console_history.tsx new file mode 100644 index 0000000000000..b23ec67422c98 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/console_history.tsx @@ -0,0 +1,225 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, useRef, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { memoize } from 'lodash'; +import moment from 'moment'; +import { + keyCodes, + EuiSpacer, + EuiIcon, + EuiTitle, + EuiFlexItem, + EuiFlexGroup, + EuiButtonEmpty, + EuiButton, +} from '@elastic/eui'; + +import { useAppContext } from '../../../../context'; +import { HistoryViewer } from './history_viewer'; + +interface Props { + close: () => void; + clearHistory: () => void; + restoreFromHistory: (req: any) => void; + requests: any[]; +} + +const CHILD_ELEMENT_PREFIX = 'historyReq'; + +export function ConsoleHistory({ close, requests, clearHistory, restoreFromHistory }: Props) { + const { + services: { settings }, + ResizeChecker, + } = useAppContext(); + + const listRef = useRef(null); + + const [viewingReq, setViewingReq] = useState(null); + const [selectedIndex, setSelectedIndex] = useState(0); + const selectedReq = useRef(null); + + const scrollIntoView = (idx: number) => { + const activeDescendant = listRef.current!.querySelector(`#${CHILD_ELEMENT_PREFIX}${idx}`); + if (activeDescendant) { + activeDescendant.scrollIntoView(); + } + }; + + const [describeReq] = useState(() => { + const _describeReq = (req: any) => { + const endpoint = req.endpoint; + const date = moment(req.time); + + let formattedDate = date.format('MMM D'); + if (date.diff(moment(), 'days') > -7) { + formattedDate = date.fromNow(); + } + + return `${endpoint} (${formattedDate})`; + }; + + (_describeReq as any).cache = new WeakMap(); + + return memoize(_describeReq); + }); + + const initialize = () => { + const nextSelectedIndex = 0; + (describeReq as any).cache = new WeakMap(); + setViewingReq(requests[nextSelectedIndex]); + selectedReq.current = requests[nextSelectedIndex]; + setSelectedIndex(nextSelectedIndex); + scrollIntoView(nextSelectedIndex); + }; + + const clear = () => { + clearHistory(); + initialize(); + }; + + const restore = (req: any = selectedReq.current) => { + restoreFromHistory(req); + }; + + useEffect(() => { + initialize(); + }, [requests]); + + /* eslint-disable */ + return ( + <> +
+ +

{i18n.translate('console.historyPage.pageTitle', { defaultMessage: 'History' })}

+
+ +
+
    { + if (ev.keyCode === keyCodes.ENTER) { + restore(); + return; + } + + let currentIdx = selectedIndex; + + if (ev.keyCode === keyCodes.UP) { + ev.preventDefault(); + --currentIdx; + } else if (ev.keyCode === keyCodes.DOWN) { + ev.preventDefault(); + ++currentIdx; + } + + const nextSelectedIndex = Math.min(Math.max(0, currentIdx), requests.length - 1); + + setViewingReq(requests[nextSelectedIndex]); + selectedReq.current = requests[nextSelectedIndex]; + setSelectedIndex(nextSelectedIndex); + scrollIntoView(nextSelectedIndex); + }} + role="listbox" + className="list-group conHistory__reqs" + tabIndex={0} + aria-activedescendant={`${CHILD_ELEMENT_PREFIX}${selectedIndex}`} + aria-label={i18n.translate('console.historyPage.requestListAriaLabel', { + defaultMessage: 'History of sent requests', + })} + > + {requests.map((req, idx) => { + const reqDescription = describeReq(req); + const isSelected = viewingReq === req; + return ( + // Ignore a11y issues on li's + // eslint-disable-next-line +
  • { + setViewingReq(req); + selectedReq.current = req; + setSelectedIndex(idx); + scrollIntoView(idx); + }} + role="option" + onMouseEnter={() => setViewingReq(req)} + onMouseLeave={() => setViewingReq(selectedReq.current)} + onDoubleClick={() => restore(req)} + aria-label={i18n.translate('console.historyPage.itemOfRequestListAriaLabel', { + defaultMessage: 'Request: {historyItem}', + values: { historyItem: reqDescription }, + })} + aria-selected={isSelected} + > + {reqDescription} + + + +
  • + ); + })} +
+ +
+ + +
+ + + + + + clear()}> + {i18n.translate('console.historyPage.clearHistoryButtonLabel', { + defaultMessage: 'Clear', + })} + + + + + + + close()}> + {i18n.translate('console.historyPage.closehistoryButtonLabel', { + defaultMessage: 'Close', + })} + + + + + restore()}> + {i18n.translate('console.historyPage.applyHistoryButtonLabel', { + defaultMessage: 'Apply', + })} + + + + + +
+ + + ); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/history_viewer.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/history_viewer.tsx new file mode 100644 index 0000000000000..b8f857299a219 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/history_viewer.tsx @@ -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 React, { useEffect, useRef } from 'react'; +import { i18n } from '@kbn/i18n'; +import $ from 'jquery'; + +import { Settings } from '../../../../../services'; +import { subscribeResizeChecker } from '../subscribe_console_resize_checker'; + +// @ts-ignore +import SenseEditor from '../../../../../../../public/quarantined/src/sense_editor/editor'; + +interface Props { + settings: Settings; + req: any | null; + ResizeChecker: any; +} + +export function HistoryViewer({ settings, ResizeChecker, req }: Props) { + const divRef = useRef(null); + const viewerRef = useRef(null); + + useEffect(() => { + const viewer = new SenseEditor($(divRef.current!)); + viewerRef.current = viewer; + viewer.renderer.setShowPrintMargin(false); + viewer.$blockScrolling = Infinity; + const unsubscribe = subscribeResizeChecker(ResizeChecker, divRef.current!, viewer); + settings.applyCurrentSettings(viewer); + return () => unsubscribe(); + }, []); + + if (viewerRef.current) { + const { current: viewer } = viewerRef; + if (req) { + const s = req.method + ' ' + req.endpoint + '\n' + (req.data || ''); + viewer.setValue(s); + viewer.clearSelection(); + } else { + viewer.getSession().setValue( + i18n.translate('console.historyPage.noHistoryTextMessage', { + defaultMessage: 'No history available', + }) + ); + } + } + + return
; +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/index.ts new file mode 100644 index 0000000000000..ba5b52f8ea4ad --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_history/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 { ConsoleHistory } from './console_history'; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_menu_actions.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_menu_actions.ts new file mode 100644 index 0000000000000..e4fdb43e68e50 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_menu_actions.ts @@ -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. + */ + +// @ts-ignore +import { getEndpointFromPosition } from '../../../../../../public/quarantined/src/autocomplete'; + +export function autoIndent(editor: any, event: any) { + editor.autoIndent(); + event.preventDefault(); + editor.focus(); +} + +export function getDocumentation(editor: any, docLinkVersion: string): Promise { + return new Promise(resolve => { + editor.getRequestsInRange((requests: any) => { + if (!requests || requests.length === 0) { + resolve(null); + return; + } + const position = requests[0].range.end; + position.column = position.column - 1; + const endpoint = getEndpointFromPosition(editor, position); + if (endpoint && endpoint.documentation && endpoint.documentation.indexOf('http') !== -1) { + const nextDocumentation = endpoint.documentation + .replace('/master/', `/${docLinkVersion}/`) + .replace('/current/', `/${docLinkVersion}/`); + resolve(nextDocumentation); + } else { + resolve(null); + } + }); + }); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/index.ts new file mode 100644 index 0000000000000..134f3de42833b --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/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 { EditorOutput, Editor } from './console_editor'; +export { ConsoleHistory } from './console_history'; +export { getDocumentation, autoIndent } from './console_menu_actions'; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/subscribe_console_resize_checker.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/subscribe_console_resize_checker.ts new file mode 100644 index 0000000000000..ae15a652d40c4 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/subscribe_console_resize_checker.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 function subscribeResizeChecker(ResizeChecker: any, $el: any, ...editors: any[]) { + const checker = new ResizeChecker($el); + checker.on('resize', () => editors.forEach(e => e.resize())); + return () => checker.destroy(); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/use_ui_ace_keyboard_mode.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/use_ui_ace_keyboard_mode.tsx new file mode 100644 index 0000000000000..2b2387e04622c --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/use_ui_ace_keyboard_mode.tsx @@ -0,0 +1,106 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, useRef } from 'react'; +import * as ReactDOM from 'react-dom'; +import { keyCodes, EuiText } from '@elastic/eui'; + +const OverlayText = () => ( + // The point of this element is for accessibility purposes, so ignore eslint error + // in this case + // + // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions + <> + Press Enter to start editing. + When you’re done, press Escape to stop editing. + +); + +export function useUIAceKeyboardMode(aceTextAreaElement: HTMLTextAreaElement | null) { + const overlayMountNode = useRef(null); + const autoCompleteVisibleRef = useRef(false); + + function onDismissOverlay(event: KeyboardEvent) { + if (event.keyCode === keyCodes.ENTER) { + event.preventDefault(); + aceTextAreaElement!.focus(); + } + } + + function enableOverlay() { + if (overlayMountNode.current) { + overlayMountNode.current.focus(); + } + } + + const isAutoCompleteVisible = () => { + const autoCompleter = document.querySelector('.ace_autocomplete'); + if (!autoCompleter) { + return false; + } + // The autoComplete is just hidden when it's closed, not removed from the DOM. + return autoCompleter.style.display !== 'none'; + }; + + const documentKeyDownListener = () => { + autoCompleteVisibleRef.current = isAutoCompleteVisible(); + }; + + const aceKeydownListener = (event: KeyboardEvent) => { + if (event.keyCode === keyCodes.ESCAPE && !autoCompleteVisibleRef.current) { + event.preventDefault(); + event.stopPropagation(); + enableOverlay(); + } + }; + + useEffect(() => { + if (aceTextAreaElement) { + // We don't control HTML elements inside of ace so we imperatively create an element + // that acts as a container and insert it just before ace's textarea element + // so that the overlay lives at the correct spot in the DOM hierarchy. + overlayMountNode.current = document.createElement('div'); + overlayMountNode.current.className = 'kbnUiAceKeyboardHint'; + overlayMountNode.current.setAttribute('role', 'application'); + overlayMountNode.current.tabIndex = 0; + overlayMountNode.current.addEventListener('focus', enableOverlay); + overlayMountNode.current.addEventListener('keydown', onDismissOverlay); + + ReactDOM.render(, overlayMountNode.current); + + aceTextAreaElement.parentElement!.insertBefore(overlayMountNode.current, aceTextAreaElement); + aceTextAreaElement.setAttribute('tabindex', '-1'); + + // Order of events: + // 1. Document capture event fires first and we check whether an autocomplete menu is open on keydown + // (not ideal because this is scoped to the entire document). + // 2. Ace changes it's state (like hiding or showing autocomplete menu) + // 3. We check what button was pressed and whether autocomplete was visible then determine + // whether it should act like a dismiss or if we should display an overlay. + document.addEventListener('keydown', documentKeyDownListener, { capture: true }); + aceTextAreaElement.addEventListener('keydown', aceKeydownListener); + } + return () => { + if (aceTextAreaElement) { + document.removeEventListener('keydown', documentKeyDownListener); + aceTextAreaElement.removeEventListener('keydown', aceKeydownListener); + document.removeChild(overlayMountNode.current!); + } + }; + }, [aceTextAreaElement]); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/index.ts new file mode 100644 index 0000000000000..44e8355611f48 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/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 { Main } from './main'; diff --git a/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/get_top_nav.ts similarity index 78% rename from src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts rename to src/legacy/core_plugins/console/np_ready/public/application/containers/main/get_top_nav.ts index 3b5fae6ff669d..330f0d1a6c1cf 100644 --- a/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/get_top_nav.ts @@ -19,13 +19,13 @@ import { i18n } from '@kbn/i18n'; -import { IScope } from 'angular'; -import { showSettingsModal } from './settings_show_modal'; - -// help -import { showHelpPanel } from './help_show_panel'; +interface Props { + onClickHistory: () => void; + onClickSettings: () => void; + onClickHelp: () => void; +} -export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) { +export function getTopNavConfig({ onClickHistory, onClickSettings, onClickHelp }: Props) { return [ { id: 'history', @@ -35,8 +35,8 @@ export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) { description: i18n.translate('console.topNav.historyTabDescription', { defaultMessage: 'History', }), - run: () => { - $scope.$evalAsync(toggleHistory); + onClick: () => { + onClickHistory(); }, testId: 'consoleHistoryButton', }, @@ -48,8 +48,8 @@ export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) { description: i18n.translate('console.topNav.settingsTabDescription', { defaultMessage: 'Settings', }), - run: () => { - showSettingsModal(); + onClick: () => { + onClickSettings(); }, testId: 'consoleSettingsButton', }, @@ -61,11 +61,8 @@ export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) { description: i18n.translate('console.topNav.helpTabDescription', { defaultMessage: 'Help', }), - run: () => { - const hideHelpPanel = showHelpPanel(); - $scope.$on('$destroy', () => { - hideHelpPanel(); - }); + onClick: () => { + onClickHelp(); }, testId: 'consoleHelpButton', }, diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/main/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/index.ts new file mode 100644 index 0000000000000..44e8355611f48 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/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 { Main } from './main'; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx new file mode 100644 index 0000000000000..8386eaf46e445 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx @@ -0,0 +1,264 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, { useCallback, useEffect, useRef, useState } from 'react'; +import { debounce } from 'lodash'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { BehaviorSubject, combineLatest } from 'rxjs'; + +// @ts-ignore +import mappings from '../../../../../public/quarantined/src/mappings'; +// @ts-ignore +import init from '../../../../../public/quarantined/src/app'; + +import { EditorOutput, Editor, ConsoleHistory } from '../editor'; +import { subscribeResizeChecker } from '../editor/legacy/subscribe_console_resize_checker'; + +import { + AutocompleteOptions, + TopNavMenu, + WelcomePanel, + DevToolsSettingsModal, + HelpPanel, + PanelsContainer, + Panel, +} from '../../components'; + +import { useAppContext } from '../../context'; +import { StorageKeys, DevToolsSettings } from '../../../services'; + +import { getTopNavConfig } from './get_top_nav'; + +const INITIAL_PANEL_WIDTH = 50; +const PANEL_MIN_WIDTH = '100px'; + +// We only run certain initialization after we know all our editors have +// been instantiated -- which is what we use the below streams for. +const inputReadySubject$ = new BehaviorSubject(null); +const outputReadySubject$ = new BehaviorSubject(null); +const editorsReady$ = combineLatest(inputReadySubject$, outputReadySubject$); + +export function Main() { + const { + services: { storage, settings, history }, + docLinkVersion, + ResizeChecker, + } = useAppContext(); + + const [editorReady, setEditorReady] = useState(false); + const [inputEditor, setInputEditor] = useState(null); + const [outputEditor, setOutputEditor] = useState(null); + const [showWelcome, setShowWelcomePanel] = useState( + () => storage.get('version_welcome_shown') !== '@@SENSE_REVISION' + ); + + const [showingHistory, setShowHistory] = useState(false); + const [showSettings, setShowSettings] = useState(false); + const [showHelp, setShowHelp] = useState(false); + + const containerRef = useRef(null); + + const onInputEditorReady = useCallback((value: any) => { + inputReadySubject$.next(value); + }, []); + + const onOutputEditorReady = useCallback((value: any) => { + outputReadySubject$.next(value); + }, []); + + const [firstPanelWidth, secondPanelWidth] = storage.get(StorageKeys.WIDTH, [ + INITIAL_PANEL_WIDTH, + INITIAL_PANEL_WIDTH, + ]); + + const onPanelWidthChange = useCallback( + debounce((widths: number[]) => { + storage.set(StorageKeys.WIDTH, widths); + }, 300), + [] + ); + + const [pastRequests, setPastRequests] = useState(() => history.getHistory()); + + const sendCurrentRequest = useCallback(() => { + inputEditor.focus(); + inputEditor.sendCurrentRequestToES(() => { + setPastRequests(history.getHistory()); + }, outputEditor); + }, [inputEditor, outputEditor]); + + const clearHistory = useCallback(() => { + history.clearHistory(); + setPastRequests(history.getHistory()); + }, []); + + const restoreFromHistory = useCallback((req: any) => { + history.restoreFromHistory(req); + }, []); + + const renderConsoleHistory = () => { + return editorReady ? ( + setShowHistory(false)} + /> + ) : null; + }; + + const refreshAutocompleteSettings = (selectedSettings: any) => { + mappings.retrieveAutoCompleteInfo(selectedSettings); + }; + + const getAutocompleteDiff = (newSettings: DevToolsSettings, prevSettings: DevToolsSettings) => { + return Object.keys(newSettings.autocomplete).filter(key => { + // @ts-ignore + return prevSettings.autocomplete[key] !== newSettings.autocomplete[key]; + }); + }; + + const fetchAutocompleteSettingsIfNeeded = ( + newSettings: DevToolsSettings, + prevSettings: DevToolsSettings + ) => { + // We'll only retrieve settings if polling is on. The expectation here is that if the user + // disables polling it's because they want manual control over the fetch request (possibly + // because it's a very expensive request given their cluster and bandwidth). In that case, + // they would be unhappy with any request that's sent automatically. + if (newSettings.polling) { + const autocompleteDiff = getAutocompleteDiff(newSettings, prevSettings); + + const isSettingsChanged = autocompleteDiff.length > 0; + const isPollingChanged = prevSettings.polling !== newSettings.polling; + + if (isSettingsChanged) { + // If the user has changed one of the autocomplete settings, then we'll fetch just the + // ones which have changed. + const changedSettings: any = autocompleteDiff.reduce( + (changedSettingsAccum: any, setting: string): any => { + changedSettingsAccum[setting] = + newSettings.autocomplete[setting as AutocompleteOptions]; + return changedSettingsAccum; + }, + {} + ); + mappings.retrieveAutoCompleteInfo(changedSettings.autocomplete); + } else if (isPollingChanged) { + // If the user has turned polling on, then we'll fetch all selected autocomplete settings. + mappings.retrieveAutoCompleteInfo(); + } + } + }; + + const onSaveSettings = async (newSettings: DevToolsSettings) => { + const prevSettings = settings.getCurrentSettings(); + settings.updateSettings(newSettings); + fetchAutocompleteSettingsIfNeeded(newSettings, prevSettings); + setShowSettings(false); + }; + + useEffect(() => { + let resizerSubscriptions: Array<() => void> = []; + const subscription = editorsReady$.subscribe(([input, output]) => { + settings.registerOutput(output.editor); + settings.registerInput(input.editor); + history.setEditor(input.editor); + + init(input.editor, output.editor, history); + + resizerSubscriptions = resizerSubscriptions.concat([ + subscribeResizeChecker(ResizeChecker, containerRef.current!, input.editor, output.editor), + subscribeResizeChecker(ResizeChecker, input.element, input.editor), + subscribeResizeChecker(ResizeChecker, output.element, output.editor), + ]); + + setInputEditor(input.editor); + setOutputEditor(output.editor); + setEditorReady(true); + }); + + return () => { + resizerSubscriptions.map(done => done()); + subscription.unsubscribe(); + }; + }, []); + + return ( +
+ + + setShowHistory(!showingHistory), + onClickSettings: () => setShowSettings(true), + onClickHelp: () => setShowHelp(!showHelp), + })} + /> + + {showingHistory ? {renderConsoleHistory()} : null} + + + + + + + + + + + + + {showWelcome ? ( + { + storage.set('version_welcome_shown', '@@SENSE_REVISION'); + setShowWelcomePanel(false); + }} + /> + ) : null} + + {showSettings ? ( + setShowSettings(false)} + refreshAutocompleteSettings={refreshAutocompleteSettings} + settings={settings.getCurrentSettings()} + /> + ) : null} + + {showHelp ? setShowHelp(false)} /> : null} +
+ ); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/application/context/app_context.tsx b/src/legacy/core_plugins/console/np_ready/public/application/context/app_context.tsx new file mode 100644 index 0000000000000..7811f27b94075 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/context/app_context.tsx @@ -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 React, { createContext, useContext } from 'react'; +import { History, Storage, Settings } from '../../services'; + +interface ContextValue { + services: { + history: History; + storage: Storage; + settings: Settings; + }; + docLinkVersion: string; + ResizeChecker: any; +} + +interface ContextProps { + value: ContextValue; + children: any; +} + +const AppContext = createContext(null as any); + +export function AppContextProvider({ children, value }: ContextProps) { + return {children}; +} + +export const useAppContext = () => { + const context = useContext(AppContext); + if (context === undefined) { + throw new Error('useAppContext must be used inside the AppContextProvider.'); + } + return context; +}; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/context/index.ts b/src/legacy/core_plugins/console/np_ready/public/application/context/index.ts new file mode 100644 index 0000000000000..27d69f5736ffe --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/context/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 { useAppContext, AppContextProvider } from './app_context'; diff --git a/src/legacy/core_plugins/console/np_ready/public/application/index.tsx b/src/legacy/core_plugins/console/np_ready/public/application/index.tsx new file mode 100644 index 0000000000000..5fb6e05aa9234 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/index.tsx @@ -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 React from 'react'; +import { AppContextProvider } from './context'; +import { Main } from './containers'; +import { createStorage, createHistory, createSettings, Settings } from '../services'; + +let settingsRef: Settings; +export function legacyBackDoorToSettings() { + return settingsRef; +} + +export function boot(deps: { docLinkVersion: string; I18nContext: any; ResizeChecker: any }) { + const { I18nContext, ResizeChecker } = deps; + + const storage = createStorage({ + engine: window.localStorage, + prefix: 'sense:', + }); + const history = createHistory({ storage }); + const settings = createSettings({ storage }); + settingsRef = settings; + + return ( + + +
+ + + ); +} diff --git a/src/legacy/core_plugins/console/public/logo.svg b/src/legacy/core_plugins/console/np_ready/public/application/logo.svg similarity index 100% rename from src/legacy/core_plugins/console/public/logo.svg rename to src/legacy/core_plugins/console/np_ready/public/application/logo.svg diff --git a/src/legacy/core_plugins/console/np_ready/public/index.ts b/src/legacy/core_plugins/console/np_ready/public/index.ts new file mode 100644 index 0000000000000..3f8d162f62d44 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/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 { PluginInitializerContext } from '../../../../../core/public'; + +import { ConsoleUIPlugin } from './plugin'; + +export { ConsoleUIPlugin as Plugin }; + +export function plugin(ctx: PluginInitializerContext) { + return new ConsoleUIPlugin(ctx); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/legacy.ts b/src/legacy/core_plugins/console/np_ready/public/legacy.ts new file mode 100644 index 0000000000000..7b8d27510d385 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/legacy.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 'brace'; +import 'brace/ext/language_tools'; +import 'brace/ext/searchbox'; +import 'brace/mode/json'; +import 'brace/mode/text'; + +/* eslint-disable @kbn/eslint/no-restricted-paths */ +import { npSetup, npStart } from 'ui/new_platform'; +import uiRoutes from 'ui/routes'; +import { DOC_LINK_VERSION } from 'ui/documentation_links'; +import { I18nContext } from 'ui/i18n'; +import { ResizeChecker } from 'ui/resize_checker'; +import 'ui/autoload/styles'; +import 'ui/capabilities/route_setup'; +/* eslint-enable @kbn/eslint/no-restricted-paths */ + +import template from '../../public/quarantined/index.html'; +import { App } from '../../../../../core/public'; + +export interface XPluginSet { + __LEGACY: { + I18nContext: any; + ResizeChecker: any; + docLinkVersion: string; + }; +} + +import { plugin } from '.'; + +const pluginInstance = plugin({} as any); + +const anyObject = {} as any; + +uiRoutes.when('/dev_tools/console', { + requireUICapability: 'dev_tools.show', + controller: function RootController($scope) { + // Stub out this config for now... + $scope.topNavMenu = []; + + $scope.initReactApp = () => { + const targetElement = document.querySelector('#consoleRoot'); + if (!targetElement) { + const message = `Could not mount Console App!`; + npSetup.core.fatalErrors.add(message); + throw new Error(message); + } + + const mockedSetupCore = { + ...npSetup.core, + application: { + register(app: App): void { + try { + app.mount(anyObject, { element: targetElement, appBasePath: '' }); + } catch (e) { + npSetup.core.fatalErrors.add(e); + } + }, + registerMountContext() {}, + }, + }; + + pluginInstance.setup(mockedSetupCore, { + ...npSetup.plugins, + __LEGACY: { + I18nContext, + ResizeChecker, + docLinkVersion: DOC_LINK_VERSION, + }, + }); + pluginInstance.start(npStart.core); + }; + }, + template, +}); diff --git a/src/legacy/core_plugins/console/np_ready/public/plugin.ts b/src/legacy/core_plugins/console/np_ready/public/plugin.ts new file mode 100644 index 0000000000000..f24224ff97b3a --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/plugin.ts @@ -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 { render, unmountComponentAtNode } from 'react-dom'; + +import { PluginInitializerContext, Plugin, CoreStart, CoreSetup } from '../../../../../core/public'; +import { XPluginSet } from './legacy'; +import { boot } from './application'; + +export class ConsoleUIPlugin implements Plugin { + // @ts-ignore + constructor(private readonly ctx: PluginInitializerContext) {} + + async setup({ application }: CoreSetup, pluginSet: XPluginSet) { + const { + __LEGACY: { docLinkVersion, I18nContext, ResizeChecker }, + } = pluginSet; + + application.register({ + id: 'console', + order: 1, + title: 'Console', + mount(ctx, { element }) { + render(boot({ docLinkVersion, I18nContext, ResizeChecker }), element); + return () => { + unmountComponentAtNode(element); + }; + }, + }); + } + + async start(core: CoreStart) {} +} diff --git a/src/legacy/core_plugins/console/np_ready/public/services/history.ts b/src/legacy/core_plugins/console/np_ready/public/services/history.ts new file mode 100644 index 0000000000000..fba33feb101b1 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/services/history.ts @@ -0,0 +1,117 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Storage } from './index'; + +export class History { + private editor: any; + + constructor(private readonly storage: Storage) {} + + setEditor(editor: any) { + this.editor = editor; + } + + // stupid simple restore function, called when the user + // chooses to restore a request from the history + // PREVENTS history from needing to know about the input + restoreFromHistory(req: any) { + const session = this.editor.getSession(); + let pos = this.editor.getCursorPosition(); + let prefix = ''; + let suffix = '\n'; + if (this.editor.parser.isStartRequestRow(pos.row)) { + pos.column = 0; + suffix += '\n'; + } else if (this.editor.parser.isEndRequestRow(pos.row)) { + const line = session.getLine(pos.row); + pos.column = line.length; + prefix = '\n\n'; + } else if (this.editor.parser.isInBetweenRequestsRow(pos.row)) { + pos.column = 0; + } else { + pos = this.editor.nextRequestEnd(pos); + prefix = '\n\n'; + } + + let s = prefix + req.method + ' ' + req.endpoint; + if (req.data) { + s += '\n' + req.data; + } + + s += suffix; + + session.insert(pos, s); + this.editor.clearSelection(); + this.editor.moveCursorTo(pos.row + prefix.length, 0); + this.editor.focus(); + } + + getHistoryKeys() { + return this.storage + .keys() + .filter((key: string) => key.indexOf('hist_elem') === 0) + .sort() + .reverse(); + } + + getHistory() { + return this.getHistoryKeys().map(key => this.storage.get(key)); + } + + addToHistory(endpoint: string, method: string, data: any) { + const keys = this.getHistoryKeys(); + keys.splice(0, 500); // only maintain most recent X; + $.each(keys, (i, k) => { + this.storage.delete(k); + }); + + const timestamp = new Date().getTime(); + const k = 'hist_elem_' + timestamp; + this.storage.set(k, { + time: timestamp, + endpoint, + method, + data, + }); + } + + updateCurrentState(content: any) { + const timestamp = new Date().getTime(); + this.storage.set('editor_state', { + time: timestamp, + content, + }); + } + + getSavedEditorState() { + const saved = this.storage.get('editor_state'); + if (!saved) return; + const { time, content } = saved; + return { time, content }; + } + + clearHistory() { + this.getHistoryKeys().forEach(key => this.storage.delete(key)); + } +} + +export function createHistory(deps: { storage: Storage }) { + return new History(deps.storage); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/services/index.ts b/src/legacy/core_plugins/console/np_ready/public/services/index.ts new file mode 100644 index 0000000000000..c54cafab7f6bc --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/services/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 { createHistory, History } from './history'; +export { createStorage, Storage, StorageKeys } from './storage'; +export { createSettings, Settings, DevToolsSettings } from './settings'; diff --git a/src/legacy/core_plugins/console/np_ready/public/services/settings.ts b/src/legacy/core_plugins/console/np_ready/public/services/settings.ts new file mode 100644 index 0000000000000..5986a8e0eddde --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/services/settings.ts @@ -0,0 +1,142 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Storage } from './index'; + +export interface DevToolsSettings { + fontSize: number; + wrapMode: boolean; + autocomplete: { + fields: boolean; + indices: boolean; + templates: boolean; + }; + polling: boolean; + tripleQuotes: boolean; +} + +export class Settings { + private input: any | null = null; + private output: any | null = null; + + constructor(private readonly storage: Storage) {} + + /** + * TODO: Slight hackiness going on here - late registration of dependencies should be refactored + */ + registerInput(input: any) { + this.input = input; + } + /** + * TODO: Slight hackiness going on here - late registration of dependencies should be refactored + */ + registerOutput(output: any) { + this.output = output; + } + + getFontSize() { + return this.storage.get('font_size', 14); + } + + setFontSize(size: any) { + this.storage.set('font_size', size); + this.applyCurrentSettings(); + return true; + } + + getWrapMode() { + return this.storage.get('wrap_mode', true); + } + + setWrapMode(mode: any) { + this.storage.set('wrap_mode', mode); + this.applyCurrentSettings(); + return true; + } + + setTripleQuotes(tripleQuotes: any) { + this.storage.set('triple_quotes', tripleQuotes); + return true; + } + + getTripleQuotes() { + return this.storage.get('triple_quotes', true); + } + + getAutocomplete() { + return this.storage.get('autocomplete_settings', { + fields: true, + indices: true, + templates: true, + }); + } + + setAutocomplete(settings: any) { + this.storage.set('autocomplete_settings', settings); + return true; + } + + getPolling() { + return this.storage.get('console_polling', true); + } + + setPolling(polling: any) { + this.storage.set('console_polling', polling); + this.applyCurrentSettings(); + return true; + } + + applyCurrentSettings(editor?: any) { + if (typeof editor === 'undefined') { + if (this.input) this.applyCurrentSettings(this.input); + if (this.output) this.applyCurrentSettings(this.output); + } else if (editor) { + editor.getSession().setUseWrapMode(this.getWrapMode()); + editor.$el.css('font-size', this.getFontSize() + 'px'); + } + } + + getCurrentSettings(): DevToolsSettings { + return { + autocomplete: this.getAutocomplete(), + wrapMode: this.getWrapMode(), + tripleQuotes: this.getTripleQuotes(), + fontSize: parseFloat(this.getFontSize()), + polling: Boolean(this.getPolling()), + }; + } + + updateSettings({ fontSize, wrapMode, tripleQuotes, autocomplete, polling }: any) { + this.setFontSize(fontSize); + this.setWrapMode(wrapMode); + this.setTripleQuotes(tripleQuotes); + this.setAutocomplete(autocomplete); + this.setPolling(polling); + this.input.focus(); + return this.getCurrentSettings(); + } +} + +interface Deps { + storage: Storage; +} + +export function createSettings({ storage }: Deps) { + return new Settings(storage); +} diff --git a/src/legacy/core_plugins/console/np_ready/public/services/storage.ts b/src/legacy/core_plugins/console/np_ready/public/services/storage.ts new file mode 100644 index 0000000000000..2ac6fc5861ad2 --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/services/storage.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 { transform, keys, startsWith } from 'lodash'; + +type IStorageEngine = typeof window.localStorage; + +export enum StorageKeys { + WIDTH = 'widths', +} + +export class Storage { + constructor(private readonly engine: IStorageEngine, private readonly prefix: string) {} + + encode(val: any) { + return JSON.stringify(val); + } + + decode(val: any) { + if (typeof val === 'string') { + return JSON.parse(val); + } + } + + encodeKey(key: string) { + return `${this.prefix}${key}`; + } + + decodeKey(key: string) { + if (startsWith(key, this.prefix)) { + return `${key.slice(this.prefix.length)}`; + } + } + + set(key: string, val: any) { + this.engine.setItem(this.encodeKey(key), this.encode(val)); + return val; + } + + has(key: string) { + return this.engine.getItem(this.encodeKey(key)) != null; + } + + get(key: string, _default?: T) { + if (this.has(key)) { + return this.decode(this.engine.getItem(this.encodeKey(key))); + } else { + return _default; + } + } + + delete(key: string) { + return this.engine.removeItem(this.encodeKey(key)); + } + + keys(): string[] { + return transform(keys(this.engine), (ours, key) => { + const ourKey = this.decodeKey(key); + if (ourKey != null) ours.push(ourKey); + }); + } +} + +export function createStorage(deps: { engine: IStorageEngine; prefix: string }) { + return new Storage(deps.engine, deps.prefix); +} diff --git a/src/legacy/core_plugins/console/np_ready/server/.gitkeep b/src/legacy/core_plugins/console/np_ready/server/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/legacy/core_plugins/console/public/README.md b/src/legacy/core_plugins/console/public/README.md new file mode 100644 index 0000000000000..3a53c46143793 --- /dev/null +++ b/src/legacy/core_plugins/console/public/README.md @@ -0,0 +1,21 @@ +## New Platform (NP) Ready vs Quarantined + +We want to move toward more modularised code in the Console app. +Part of the effort means separating out different console components +like: + +- The language parser +- The editor rendering component +- Autocomplete +- The UI container components + +In addition to this effort we want to bring Console in line with NP +requirements and ensure that we are not using angular and public ui +in this app anymore. + +The quarantined folder contains all of the code that has not been cleared +for living in the new platform as it has not been properly refactored +or has dependencies on, for example, UI public. + +Over time, the quarantined part of the code should shrink to nothing +and we should only have NP ready code. diff --git a/src/legacy/core_plugins/console/public/console.js b/src/legacy/core_plugins/console/public/console.js deleted file mode 100644 index 2cb8d299d993f..0000000000000 --- a/src/legacy/core_plugins/console/public/console.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 uiRoutes from 'ui/routes'; -import template from './index.html'; - -require('brace'); - -require('ui/autoload/styles'); -require('ui/capabilities/route_setup'); - -require('./src/controllers/sense_controller'); -require('./src/directives/sense_history'); -require('./src/directives/console_menu_directive'); - - -uiRoutes.when('/dev_tools/console', { - requireUICapability: 'dev_tools.show', - controller: 'SenseController', - template, -}); diff --git a/src/legacy/core_plugins/console/public/index.html b/src/legacy/core_plugins/console/public/index.html deleted file mode 100644 index 91bcb05bf64cc..0000000000000 --- a/src/legacy/core_plugins/console/public/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - -
-
-
    -
    - - - - - -
    - -
    GET _search - { - "query": { "match_all": {} } - }
    - -
    -
    -
    -
    {}
    -
    -
    -
    -
    -
    -
    diff --git a/src/legacy/core_plugins/console/public/_app.scss b/src/legacy/core_plugins/console/public/quarantined/_app.scss similarity index 80% rename from src/legacy/core_plugins/console/public/_app.scss rename to src/legacy/core_plugins/console/public/quarantined/_app.scss index f3de2a9ee9e5b..5fd2cd080d06d 100644 --- a/src/legacy/core_plugins/console/public/_app.scss +++ b/src/legacy/core_plugins/console/public/quarantined/_app.scss @@ -1,19 +1,26 @@ +// TODO: Move all of the styles here (should be modularised by, e.g., CSS-in-JS or CSS modules). +#consoleRoot { + height: 100%; + // Make sure the editor actions don't create scrollbars on this container + // SASSTODO: Uncomment when tooltips are EUI-ified (inside portals) + overflow: hidden; +} + +.consoleContainer { + padding: $euiSizeS; +} + .conApp { display: flex; flex: 1 1 auto; - position: relative; - padding: $euiSizeS; - // Make sure the editor actions don't create scrollbars on this container - // SASSTODO: Uncomment when tooltips are EUI-ified (inside portals) - // overflow: hidden; } .conApp__editor { - // Default size of left side is half the large breakpoint - // but this is inline overridden by the resizer - width: map-get($euiBreakpoints, "l") / 2; + width: 100%; display: flex; flex: 0 0 auto; + + // Required on IE11 to render ace editor correctly after first input. position: relative; } @@ -24,6 +31,7 @@ .conApp__editorContent, .conApp__outputContent { + height: 100%; flex: 1 1 1px; } diff --git a/src/legacy/core_plugins/console/public/hacks/register.js b/src/legacy/core_plugins/console/public/quarantined/hacks/register.js similarity index 94% rename from src/legacy/core_plugins/console/public/hacks/register.js rename to src/legacy/core_plugins/console/public/quarantined/hacks/register.js index 4869ae4b0ed00..b5df1c1af99c5 100644 --- a/src/legacy/core_plugins/console/public/hacks/register.js +++ b/src/legacy/core_plugins/console/public/quarantined/hacks/register.js @@ -24,7 +24,7 @@ DevToolsRegistryProvider.register(() => ({ order: 1, name: 'console', display: i18n.translate('console.consoleDisplayName', { - defaultMessage: 'Console' + defaultMessage: 'Console', }), - url: '#/dev_tools/console' + url: '#/dev_tools/console', })); diff --git a/src/legacy/core_plugins/console/public/quarantined/index.html b/src/legacy/core_plugins/console/public/quarantined/index.html new file mode 100644 index 0000000000000..66a693d4b2af7 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/index.html @@ -0,0 +1,3 @@ + +
    +
    diff --git a/src/legacy/core_plugins/console/public/index.scss b/src/legacy/core_plugins/console/public/quarantined/index.scss similarity index 100% rename from src/legacy/core_plugins/console/public/index.scss rename to src/legacy/core_plugins/console/public/quarantined/index.scss diff --git a/src/legacy/core_plugins/console/public/quarantined/src/__tests__/app.js b/src/legacy/core_plugins/console/public/quarantined/src/__tests__/app.js new file mode 100644 index 0000000000000..a1984bca3ab02 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/__tests__/app.js @@ -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 sinon from 'sinon'; +import $ from 'jquery'; + +import mappings from '../mappings'; +import init from '../app'; + +const history = { getSavedEditorState() {}, }; + +describe('console app initialization', () => { + const sandbox = sinon.createSandbox(); + + let inputMock; + let outputMock; + let ajaxDoneStub; + beforeEach(() => { + ajaxDoneStub = sinon.stub(); + sandbox.stub($, 'ajax').returns({ done: ajaxDoneStub }); + sandbox.stub(mappings, 'retrieveAutoCompleteInfo'); + + inputMock = { + update: sinon.stub(), + moveToNextRequestEdge: sinon.stub(), + highlightCurrentRequestsAndUpdateActionBar: sinon.stub(), + updateActionsBar: sinon.stub(), + getSession: sinon.stub().returns({ on() {} }), + }; + + outputMock = { + update: sinon.stub(), + }; + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('correctly loads state from any external HTTPS links.', () => { + const mockContent = {}; + ajaxDoneStub.yields(mockContent); + + init(inputMock, outputMock, history, 'https://state.link.com/content'); + + sinon.assert.calledOnce($.ajax); + sinon.assert.calledWithExactly($.ajax, { + url: 'https://state.link.com/content', + dataType: 'text', + kbnXsrfToken: false, + }); + + sinon.assert.calledTwice(inputMock.moveToNextRequestEdge); + sinon.assert.calledWithExactly(inputMock.moveToNextRequestEdge, true); + sinon.assert.calledOnce(inputMock.highlightCurrentRequestsAndUpdateActionBar); + sinon.assert.calledOnce(inputMock.updateActionsBar); + sinon.assert.calledOnce(inputMock.update); + sinon.assert.calledWithExactly(inputMock.update, sinon.match.same(mockContent)); + + sinon.assert.calledOnce(outputMock.update); + sinon.assert.calledWithExactly(outputMock.update, ''); + }); + + it('correctly loads state from GitHub API HTTPS links.', () => { + const mockContent = {}; + ajaxDoneStub.yields(mockContent); + + init(inputMock, outputMock, history, 'https://api.github.com/content'); + + sinon.assert.calledOnce($.ajax); + sinon.assert.calledWithExactly($.ajax, { + url: 'https://api.github.com/content', + dataType: 'text', + kbnXsrfToken: false, + headers: { Accept: 'application/vnd.github.v3.raw' }, + }); + + sinon.assert.calledTwice(inputMock.moveToNextRequestEdge); + sinon.assert.calledWithExactly(inputMock.moveToNextRequestEdge, true); + sinon.assert.calledOnce(inputMock.highlightCurrentRequestsAndUpdateActionBar); + sinon.assert.calledOnce(inputMock.updateActionsBar); + sinon.assert.calledOnce(inputMock.update); + sinon.assert.calledWithExactly(inputMock.update, sinon.match.same(mockContent)); + + sinon.assert.calledOnce(outputMock.update); + sinon.assert.calledWithExactly(outputMock.update, ''); + }); +}); diff --git a/src/legacy/core_plugins/console/public/src/__tests__/utils.js b/src/legacy/core_plugins/console/public/quarantined/src/__tests__/utils.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/__tests__/utils.js rename to src/legacy/core_plugins/console/public/quarantined/src/__tests__/utils.js diff --git a/src/legacy/core_plugins/console/public/quarantined/src/app.js b/src/legacy/core_plugins/console/public/quarantined/src/app.js new file mode 100644 index 0000000000000..610e006f76e0f --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/app.js @@ -0,0 +1,96 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 $ = require('jquery'); +const mappings = require('./mappings'); + +const DEFAULT_INPUT_VALUE = `GET _search +{ + "query": { + "match_all": {} + } +}`; + +export default function init(input, output, history, sourceLocation = 'stored') { + $(document.body).removeClass('fouc'); + + // set the value of the input and clear the output + function resetToValues(content) { + input.update(content != null ? content : DEFAULT_INPUT_VALUE); + output.update(''); + } + + function setupAutosave() { + let timer; + const saveDelay = 500; + + input.getSession().on('change', function onChange() { + if (timer) { + timer = clearTimeout(timer); + } + timer = setTimeout(saveCurrentState, saveDelay); + }); + } + + function saveCurrentState() { + try { + const content = input.getValue(); + history.updateCurrentState(content); + } catch (e) { + console.log('Ignoring saving error: ' + e); + } + } + function loadSavedState() { + const previousSaveState = history.getSavedEditorState(); + + if (sourceLocation === 'stored') { + if (previousSaveState) { + resetToValues(previousSaveState.content); + } else { + resetToValues(); + } + } else if (/^https?:\/\//.test(sourceLocation)) { + const loadFrom = { + url: sourceLocation, + // Having dataType here is required as it doesn't allow jQuery to `eval` content + // coming from the external source thereby preventing XSS attack. + dataType: 'text', + kbnXsrfToken: false, + }; + + if (/https?:\/\/api.github.com/.test(sourceLocation)) { + loadFrom.headers = { Accept: 'application/vnd.github.v3.raw' }; + } + + $.ajax(loadFrom).done(data => { + resetToValues(data); + input.moveToNextRequestEdge(true); + input.highlightCurrentRequestsAndUpdateActionBar(); + input.updateActionsBar(); + }); + } else { + resetToValues(); + } + input.moveToNextRequestEdge(true); + } + + setupAutosave(); + loadSavedState(); + mappings.retrieveAutoCompleteInfo(); +} diff --git a/src/legacy/core_plugins/console/public/quarantined/src/autocomplete.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete.js new file mode 100644 index 0000000000000..cec82e9690ead --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete.js @@ -0,0 +1,1010 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + getTopLevelUrlCompleteComponents, + getEndpointBodyCompleteComponents, + getGlobalAutocompleteComponents, + getUnmatchedEndpointComponents +} from './kb'; +import utils from './utils'; +import { populateContext } from './autocomplete/engine'; +import { URL_PATH_END_MARKER } from './autocomplete/components'; +import _ from 'lodash'; +import ace from 'brace'; +import { i18n } from '@kbn/i18n'; + +const AceRange = ace.acequire('ace/range').Range; + +let LAST_EVALUATED_TOKEN = null; + +function isUrlParamsToken(token) { + switch ((token || {}).type) { + case 'url.param': + case 'url.equal': + case 'url.value': + case 'url.questionmark': + case 'url.amp': + return true; + default: + return false; + } +} +function getCurrentMethodAndTokenPaths(editor, pos, forceEndOfUrl) { + const tokenIter = editor.iterForPosition(pos.row, pos.column); + const startPos = pos; + let bodyTokenPath = []; + const ret = {}; + + const STATES = { + looking_for_key: 0, // looking for a key but without jumping over anything but white space and colon. + looking_for_scope_start: 1, // skip everything until scope start + start: 3 + }; + let state = STATES.start; + + // initialization problems - + let t = tokenIter.getCurrentToken(); + if (t) { + if (startPos.column === 0) { + // if we are at the beginning of the line, the current token is the one after cursor, not before which + // deviates from the standard. + t = tokenIter.stepBackward(); + state = STATES.looking_for_scope_start; + } + } + else { + if (startPos.column === 0) { + // empty lines do no have tokens, move one back + t = tokenIter.stepBackward(); + state = STATES.start; + } + } + + let walkedSomeBody = false; + + // climb one scope at a time and get the scope key + for (; t && t.type.indexOf('url') === -1 && t.type !== 'method'; t = tokenIter.stepBackward()) { + + if (t.type !== 'whitespace') { + walkedSomeBody = true; + } // marks we saw something + + switch (t.type) { + case 'variable': + if (state === STATES.looking_for_key) { + bodyTokenPath.unshift(t.value.trim().replace(/"/g, '')); + } + state = STATES.looking_for_scope_start; // skip everything until the beginning of this scope + break; + + case 'paren.lparen': + bodyTokenPath.unshift(t.value); + if (state === STATES.looking_for_scope_start) { + // found it. go look for the relevant key + state = STATES.looking_for_key; + } + break; + case 'paren.rparen': + // reset he search for key + state = STATES.looking_for_scope_start; + // and ignore this sub scope.. + let parenCount = 1; + t = tokenIter.stepBackward(); + while (t && parenCount > 0) { + switch (t.type) { + case 'paren.lparen': + parenCount--; + break; + case 'paren.rparen': + parenCount++; + break; + } + if (parenCount > 0) { + t = tokenIter.stepBackward(); + } + } + if (!t) // oops we run out.. we don't know what's up return null; + { + return {}; + } + continue; + case 'punctuation.end_triple_quote': + // reset the search for key + state = STATES.looking_for_scope_start; + for (t = tokenIter.stepBackward(); t; t = tokenIter.stepBackward()) { + if (t.type === 'punctuation.start_triple_quote') { + t = tokenIter.stepBackward(); + break; + } + } + if (!t) // oops we run out.. we don't know what's up return null; + { + return {}; + } + continue; + case 'punctuation.start_triple_quote': + if (state === STATES.start) { + state = STATES.looking_for_key; + } + else if (state === STATES.looking_for_key) { + state = STATES.looking_for_scope_start; + } + bodyTokenPath.unshift('"""'); + continue; + case 'string': + case 'constant.numeric': + case 'constant.language.boolean': + case 'text': + if (state === STATES.start) { + state = STATES.looking_for_key; + } + else if (state === STATES.looking_for_key) { + state = STATES.looking_for_scope_start; + } + + break; + case 'punctuation.comma': + if (state === STATES.start) { + state = STATES.looking_for_scope_start; + } + break; + case 'punctuation.colon': + case 'whitespace': + if (state === STATES.start) { + state = STATES.looking_for_key; + } + break; // skip white space + + } + } + + if (walkedSomeBody && (!bodyTokenPath || bodyTokenPath.length === 0)) { + // we had some content and still no path -> the cursor is position after a closed body -> no auto complete + return {}; + } + ret.urlTokenPath = []; + if (tokenIter.getCurrentTokenRow() === startPos.row) { + if (t && (t.type === 'url.part' || t.type === 'url.param' || t.type === 'url.value')) { + // we are forcing the end of the url for the purposes of determining an endpoint + if (forceEndOfUrl && t.type === 'url.part') { + ret.urlTokenPath.push(t.value); + ret.urlTokenPath.push(URL_PATH_END_MARKER); + } + // we are on the same line as cursor and dealing with a url. Current token is not part of the context + t = tokenIter.stepBackward(); + // This will force method parsing + while (t.type === 'whitespace') { + t = tokenIter.stepBackward(); + } + } + bodyTokenPath = null; // no not on a body line. + } + + ret.bodyTokenPath = bodyTokenPath; + + ret.urlParamsTokenPath = null; + ret.requestStartRow = tokenIter.getCurrentTokenRow(); + let curUrlPart; + + while (t && isUrlParamsToken(t)) { + switch (t.type) { + case 'url.value': + if (Array.isArray(curUrlPart)) { + curUrlPart.unshift(t.value); + } + else if (curUrlPart) { + curUrlPart = [t.value, curUrlPart]; + } + else { + curUrlPart = t.value; + } + break; + case 'url.comma': + if (!curUrlPart) { + curUrlPart = []; + } + else if (!Array.isArray(curUrlPart)) { + curUrlPart = [curUrlPart]; + } + break; + case 'url.param': + const v = curUrlPart; + curUrlPart = {}; + curUrlPart[t.value] = v; + break; + case 'url.amp': + case 'url.questionmark': + if (!ret.urlParamsTokenPath) { + ret.urlParamsTokenPath = []; + } + ret.urlParamsTokenPath.unshift(curUrlPart || {}); + curUrlPart = null; + break; + } + t = tokenIter.stepBackward(); + } + + curUrlPart = null; + while (t && t.type.indexOf('url') !== -1) { + switch (t.type) { + case 'url.part': + if (Array.isArray(curUrlPart)) { + curUrlPart.unshift(t.value); + } + else if (curUrlPart) { + curUrlPart = [t.value, curUrlPart]; + } + else { + curUrlPart = t.value; + } + break; + case 'url.comma': + if (!curUrlPart) { + curUrlPart = []; + } + else if (!Array.isArray(curUrlPart)) { + curUrlPart = [curUrlPart]; + } + break; + case 'url.slash': + if (curUrlPart) { + ret.urlTokenPath.unshift(curUrlPart); + curUrlPart = null; + } + break; + } + t = editor.parser.prevNonEmptyToken(tokenIter); + } + + if (curUrlPart) { + ret.urlTokenPath.unshift(curUrlPart); + } + + if (!ret.bodyTokenPath && !ret.urlParamsTokenPath) { + + if (ret.urlTokenPath.length > 0) { + // // started on the url, first token is current token + ret.otherTokenValues = ret.urlTokenPath[0]; + } + } + else { + // mark the url as completed. + ret.urlTokenPath.push(URL_PATH_END_MARKER); + } + + if (t && t.type === 'method') { + ret.method = t.value; + } + return ret; +} +export function getEndpointFromPosition(editor, pos) { + const context = { ...getCurrentMethodAndTokenPaths(editor, pos, true) }; + const components = getTopLevelUrlCompleteComponents(context.method); + populateContext(context.urlTokenPath, context, editor, true, components); + return context.endpoint; +} +export default function (editor) { + + function isUrlPathToken(token) { + switch ((token || {}).type) { + case 'url.slash': + case 'url.comma': + case 'url.part': + return true; + default: + return false; + } + } + + function addMetaToTermsList(list, meta, template) { + return _.map(list, function (t) { + if (typeof t !== 'object') { + t = { name: t }; + } + return _.defaults(t, { meta: meta, template: template }); + }); + } + + function applyTerm(term) { + const session = editor.getSession(); + + const context = term.context; + + // make sure we get up to date replacement info. + addReplacementInfoToContext(context, editor.getCursorPosition(), term.insertValue); + + let termAsString; + if (context.autoCompleteType === 'body') { + termAsString = typeof term.insertValue === 'string' ? '"' + term.insertValue + '"' : term.insertValue + ''; + if (term.insertValue === '[' || term.insertValue === '{') { + termAsString = ''; + } + } + else { + termAsString = term.insertValue + ''; + } + + let valueToInsert = termAsString; + let templateInserted = false; + if (context.addTemplate && !_.isUndefined(term.template) && !_.isNull(term.template)) { + let indentedTemplateLines; + // In order to allow triple quoted strings in template completion we check the `__raw_` + // attribute to determine whether this template should go through JSON formatting. + if (term.template.__raw && term.template.value) { + indentedTemplateLines = term.template.value.split('\n'); + } else { + indentedTemplateLines = utils.jsonToString(term.template, true).split('\n'); + } + let currentIndentation = session.getLine(context.rangeToReplace.start.row); + currentIndentation = currentIndentation.match(/^\s*/)[0]; + for (let i = 1; i < indentedTemplateLines.length; i++) // skip first line + {indentedTemplateLines[i] = currentIndentation + indentedTemplateLines[i];} + + valueToInsert += ': ' + indentedTemplateLines.join('\n'); + templateInserted = true; + } + else { + templateInserted = true; + if (term.value === '[') { + valueToInsert += '[]'; + } + else if (term.value === '{') { + valueToInsert += '{}'; + } + else { + templateInserted = false; + } + } + + valueToInsert = context.prefixToAdd + valueToInsert + context.suffixToAdd; + + // disable listening to the changes we are making. + removeChangeListener(); + + if (context.rangeToReplace.start.column !== context.rangeToReplace.end.column) { + session.replace(context.rangeToReplace, valueToInsert); + } + else { + editor.insert(valueToInsert); + } + + editor.clearSelection(); // for some reason the above changes selection + + // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do. + let newPos = { + row: context.rangeToReplace.start.row, + column: context.rangeToReplace.start.column + termAsString.length + context.prefixToAdd.length + + (templateInserted ? 0 : context.suffixToAdd.length) + }; + + const tokenIter = editor.iterForPosition(newPos.row, newPos.column); + + if (context.autoCompleteType === 'body') { + // look for the next place stand, just after a comma, { + let nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'paren.rparen': + newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; + break; + case 'punctuation.colon': + nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + if ((nonEmptyToken || {}).type === 'paren.lparen') { + nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; + if (nonEmptyToken && nonEmptyToken.value.indexOf('"') === 0) { + newPos.column++; + } // don't stand on " + } + break; + case 'paren.lparen': + case 'punctuation.comma': + tokenIter.stepForward(); + newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; + break; + } + editor.moveCursorToPosition(newPos); + } + + // re-enable listening to typing + addChangeListener(); + } + + function getAutoCompleteContext(editor, session, pos) { + // deduces all the parameters need to position and insert the auto complete + const context = { + autoCompleteSet: null, // instructions for what can be here + endpoint: null, + urlPath: null, + method: null, + activeScheme: null, + editor: editor + }; + + // context.updatedForToken = session.getTokenAt(pos.row, pos.column); + // + // if (!context.updatedForToken) + // context.updatedForToken = { value: "", start: pos.column }; // empty line + // + // context.updatedForToken.row = pos.row; // extend + + context.autoCompleteType = getAutoCompleteType(pos); + switch (context.autoCompleteType) { + case 'path': + addPathAutoCompleteSetToContext(context, pos); + break; + case 'url_params': + addUrlParamsAutoCompleteSetToContext(context, pos); + break; + case 'method': + addMethodAutoCompleteSetToContext(context, pos); + break; + case 'body': + addBodyAutoCompleteSetToContext(context, pos); + break; + default: + return null; + } + + if (!context.autoCompleteSet) { + return null; // nothing to do.. + } + + addReplacementInfoToContext(context, pos); + + context.createdWithToken = _.clone(context.updatedForToken); + + return context; + } + + function getAutoCompleteType(pos) { + // return "method", "path" or "body" to determine auto complete type. + + let rowMode = editor.parser.getRowParseMode(); + + //noinspection JSBitwiseOperatorUsage + if (rowMode & editor.parser.MODE.IN_REQUEST) { + return 'body'; + } + //noinspection JSBitwiseOperatorUsage + if (rowMode & editor.parser.MODE.REQUEST_START) { + // on url path, url params or method. + const tokenIter = editor.iterForPosition(pos.row, pos.column); + let t = tokenIter.getCurrentToken(); + + while (t.type === 'url.comma') { + t = tokenIter.stepBackward(); + } + switch (t.type) { + case 'method': + return 'method'; + case 'whitespace': + t = editor.parser.prevNonEmptyToken(tokenIter); + + switch ((t || {}).type) { + case 'method': + // we moved one back + return 'path'; + break; + default: + if (isUrlPathToken(t)) { + return 'path'; + } + if (isUrlParamsToken(t)) { + return 'url_params'; + } + return null; + } + break; + default: + if (isUrlPathToken(t)) { + return 'path'; + } + if (isUrlParamsToken(t)) { + return 'url_params'; + } + return null; + } + } + + // after start to avoid single line url only requests + //noinspection JSBitwiseOperatorUsage + if (rowMode & editor.parser.MODE.REQUEST_END) { + return 'body'; + } + + // in between request on an empty + if ((editor.getSession().getLine(pos.row) || '').trim() === '') { + // check if the previous line is a single line begging of a new request + rowMode = editor.parser.getRowParseMode(pos.row - 1); + //noinspection JSBitwiseOperatorUsage + if ((rowMode & editor.parser.MODE.REQUEST_START) && (rowMode & editor.parser.MODE.REQUEST_END)) { + return 'body'; + } + //o.w suggest a method + return 'method'; + } + + return null; + } + + function addReplacementInfoToContext(context, pos, replacingTerm) { + // extract the initial value, rangeToReplace & textBoxPosition + + // Scenarios for current token: + // - Nice token { "bla|" + // - Broken text token { bla| + // - No token : { | + // - Broken scenario { , bla| + // - Nice token, broken before: {, "bla" + + const session = editor.getSession(); + + context.updatedForToken = _.clone(session.getTokenAt(pos.row, pos.column)); + if (!context.updatedForToken) { + context.updatedForToken = { value: '', start: pos.column }; + } // empty line + + let anchorToken = context.createdWithToken; + if (!anchorToken) { + anchorToken = context.updatedForToken; + } + + switch (context.updatedForToken.type) { + case 'variable': + case 'string': + case 'text': + case 'constant.numeric': + case 'constant.language.boolean': + case 'method': + case 'url.index': + case 'url.type': + case 'url.id': + case 'url.method': + case 'url.endpoint': + case 'url.part': + case 'url.param': + case 'url.value': + context.rangeToReplace = new AceRange( + pos.row, anchorToken.start, pos.row, + context.updatedForToken.start + context.updatedForToken.value.length + ); + context.replacingToken = true; + break; + default: + if (replacingTerm && context.updatedForToken.value === replacingTerm) { + context.rangeToReplace = new AceRange( + pos.row, anchorToken.start, pos.row, + context.updatedForToken.start + context.updatedForToken.value.length + ); + context.replacingToken = true; + } + else { + // standing on white space, quotes or another punctuation - no replacing + context.rangeToReplace = new AceRange( + pos.row, pos.column, pos.row, pos.column + ); + context.replacingToken = false; + } + break; + } + + context.textBoxPosition = { row: context.rangeToReplace.start.row, column: context.rangeToReplace.start.column }; + + switch (context.autoCompleteType) { + case 'path': + addPathPrefixSuffixToContext(context); + break; + case 'url_params': + addUrlParamsPrefixSuffixToContext(context); + break; + case 'method': + addMethodPrefixSuffixToContext(context); + break; + case 'body': + addBodyPrefixSuffixToContext(context); + break; + } + } + + function addBodyPrefixSuffixToContext(context) { + // Figure out what happens next to the token to see whether it needs trailing commas etc. + + // Templates will be used if not destroying existing structure. + // -> token : {} or token ]/} or token , but not token : SOMETHING ELSE + + context.prefixToAdd = ''; + context.suffixToAdd = ''; + + let tokenIter = editor.iterForCurrentLoc(); + let nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'NOTOKEN': + case 'paren.lparen': + case 'paren.rparen': + case 'punctuation.comma': + context.addTemplate = true; + break; + case 'punctuation.colon': + // test if there is an empty object - if so we replace it + context.addTemplate = false; + + nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + if (!(nonEmptyToken && nonEmptyToken.value === '{')) { + break; + } + nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + if (!(nonEmptyToken && nonEmptyToken.value === '}')) { + break; + } + context.addTemplate = true; + // extend range to replace to include all up to token + context.rangeToReplace.end.row = tokenIter.getCurrentTokenRow(); + context.rangeToReplace.end.column = tokenIter.getCurrentTokenColumn() + nonEmptyToken.value.length; + + // move one more time to check if we need a trailing comma + nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'NOTOKEN': + case 'paren.rparen': + case 'punctuation.comma': + case 'punctuation.colon': + break; + default: + context.suffixToAdd = ', '; + } + + break; + default: + context.addTemplate = true; + context.suffixToAdd = ', '; + break; // for now play safe and do nothing. May be made smarter. + } + + // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do. + tokenIter = editor.iterForCurrentLoc(); + nonEmptyToken = tokenIter.getCurrentToken(); + let insertingRelativeToToken; // -1 is before token, 0 middle, +1 after token + if (context.replacingToken) { + insertingRelativeToToken = 0; + } + else { + const pos = editor.getCursorPosition(); + if (pos.column === context.updatedForToken.start) { + insertingRelativeToToken = -1; + } + else if (pos.column < context.updatedForToken.start + context.updatedForToken.value.length) { + insertingRelativeToToken = 0; + } + else { + insertingRelativeToToken = 1; + } + + } + // we should actually look at what's happening before this token + if (editor.parser.isEmptyToken(nonEmptyToken) || insertingRelativeToToken <= 0) { + nonEmptyToken = editor.parser.prevNonEmptyToken(tokenIter); + } + + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'NOTOKEN': + case 'paren.lparen': + case 'punctuation.comma': + case 'punctuation.colon': + case 'method': + break; + default: + if (nonEmptyToken && nonEmptyToken.type.indexOf('url') < 0) { + context.prefixToAdd = ', '; + } + } + + return context; + } + + function addUrlParamsPrefixSuffixToContext(context) { + context.prefixToAdd = ''; + context.suffixToAdd = ''; + } + + function addMethodPrefixSuffixToContext(context) { + context.prefixToAdd = ''; + context.suffixToAdd = ''; + const tokenIter = editor.iterForCurrentLoc(); + const row = tokenIter.getCurrentTokenRow(); + const t = editor.parser.nextNonEmptyToken(tokenIter); + + if (tokenIter.getCurrentTokenRow() !== row || !t) { + // we still have nothing next to the method, add a space.. + context.suffixToAdd = ' '; + } + } + + function addPathPrefixSuffixToContext(context) { + context.prefixToAdd = ''; + context.suffixToAdd = ''; + } + + function addMethodAutoCompleteSetToContext(context) { + context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({ + name: m, + score: -i, + meta: i18n.translate('console.autocomplete.addMethodMetaText', { defaultMessage: 'method' }), + })); + } + + + function addPathAutoCompleteSetToContext(context, pos) { + const ret = getCurrentMethodAndTokenPaths(editor, pos); + context.method = ret.method; + context.token = ret.token; + context.otherTokenValues = ret.otherTokenValues; + context.urlTokenPath = ret.urlTokenPath; + const components = getTopLevelUrlCompleteComponents(context.method); + populateContext(ret.urlTokenPath, context, editor, true, components); + + + context.autoCompleteSet = addMetaToTermsList(context.autoCompleteSet, 'endpoint'); + } + + function addUrlParamsAutoCompleteSetToContext(context, pos) { + const ret = getCurrentMethodAndTokenPaths(editor, pos); + context.method = ret.method; + context.otherTokenValues = ret.otherTokenValues; + context.urlTokenPath = ret.urlTokenPath; + if (!ret.urlTokenPath) { // zero length tokenPath is true + + console.log('Can\'t extract a valid url token path.'); + return context; + } + + populateContext(ret.urlTokenPath, context, editor, false, getTopLevelUrlCompleteComponents(context.method)); + + if (!context.endpoint) { + console.log('couldn\'t resolve an endpoint.'); + return context; + } + + if (!ret.urlParamsTokenPath) { // zero length tokenPath is true + console.log('Can\'t extract a valid urlParams token path.'); + return context; + } + let tokenPath = []; + const currentParam = ret.urlParamsTokenPath.pop(); + if (currentParam) { + tokenPath = Object.keys(currentParam); // single key object + context.otherTokenValues = currentParam[tokenPath[0]]; + } + + populateContext(tokenPath, context, editor, true, + context.endpoint.paramsAutocomplete.getTopLevelComponents(context.method)); + return context; + } + + function addBodyAutoCompleteSetToContext(context, pos) { + + const ret = getCurrentMethodAndTokenPaths(editor, pos); + context.method = ret.method; + context.otherTokenValues = ret.otherTokenValues; + context.urlTokenPath = ret.urlTokenPath; + context.requestStartRow = ret.requestStartRow; + if (!ret.urlTokenPath) { // zero length tokenPath is true + console.log('Can\'t extract a valid url token path.'); + return context; + } + + populateContext(ret.urlTokenPath, context, editor, false, getTopLevelUrlCompleteComponents(context.method)); + + context.bodyTokenPath = ret.bodyTokenPath; + if (!ret.bodyTokenPath) { // zero length tokenPath is true + + console.log('Can\'t extract a valid body token path.'); + return context; + } + + // needed for scope linking + global term resolving + context.endpointComponentResolver = getEndpointBodyCompleteComponents; + context.globalComponentResolver = getGlobalAutocompleteComponents; + let components; + if (context.endpoint) { + components = context.endpoint.bodyAutocompleteRootComponents; + } + else { + components = getUnmatchedEndpointComponents(); + } + populateContext(ret.bodyTokenPath, context, editor, true, components); + + return context; + } + + + + const evaluateCurrentTokenAfterAChange = _.debounce(function evaluateCurrentTokenAfterAChange(pos) { + const session = editor.getSession(); + let currentToken = session.getTokenAt(pos.row, pos.column); + + if (!currentToken) { + if (pos.row === 0) { + LAST_EVALUATED_TOKEN = null; + return; + } + currentToken = { start: 0, value: '' }; // empty row + } + + currentToken.row = pos.row; // extend token with row. Ace doesn't supply it by default + if (editor.parser.isEmptyToken(currentToken)) { + // empty token. check what's coming next + const nextToken = session.getTokenAt(pos.row, pos.column + 1); + if (editor.parser.isEmptyToken(nextToken)) { + // Empty line, or we're not on the edge of current token. Save the current position as base + currentToken.start = pos.column; + LAST_EVALUATED_TOKEN = currentToken; + } + else { + nextToken.row = pos.row; + LAST_EVALUATED_TOKEN = nextToken; + } + return; + } + + if (!LAST_EVALUATED_TOKEN) { + LAST_EVALUATED_TOKEN = currentToken; + return; // wait for the next typing. + } + + if (LAST_EVALUATED_TOKEN.start !== currentToken.start || LAST_EVALUATED_TOKEN.row !== currentToken.row + || LAST_EVALUATED_TOKEN.value === currentToken.value) { + // not on the same place or nothing changed, cache and wait for the next time + LAST_EVALUATED_TOKEN = currentToken; + return; + } + + // don't automatically open the auto complete if some just hit enter (new line) or open a parentheses + switch (currentToken.type || 'UNKNOWN') { + case 'paren.lparen': + case 'paren.rparen': + case 'punctuation.colon': + case 'punctuation.comma': + case 'UNKNOWN': + return; + } + + LAST_EVALUATED_TOKEN = currentToken; + editor.execCommand('startAutocomplete'); + }, 100); + + function editorChangeListener() { + const cursor = editor.selection.lead; + if (editor.__ace.completer && editor.__ace.completer.activated) { + return; + } + evaluateCurrentTokenAfterAChange(cursor); + } + + function addChangeListener() { + editor.on('changeSelection', editorChangeListener); + } + + function removeChangeListener() { + editor.off('changeSelection', editorChangeListener); + } + + function getCompletions(aceEditor, session, pos, prefix, callback) { + try { + + const context = getAutoCompleteContext(editor, session, pos); + if (!context) { + callback(null, []); + } + else { + const terms = _.map( + context + .autoCompleteSet + .filter(term => Boolean(term) && term.name != null), + function (term) { + if (typeof term !== 'object') { + term = { + name: term + }; + } else { + term = _.clone(term); + } + const defaults = { + value: term.name, + meta: 'API', + score: 0, + context: context, + }; + // we only need out custom insertMatch behavior for the body + if (context.autoCompleteType === 'body') { + defaults.completer = { + insertMatch: function () { + return applyTerm(term); + } + }; + } + return _.defaults(term, defaults); + }); + + terms.sort(function (t1, t2) { + /* score sorts from high to low */ + if (t1.score > t2.score) { + return -1; + } + if (t1.score < t2.score) { + return 1; + } + /* names sort from low to high */ + if (t1.name < t2.name) { + return -1; + } + if (t1.name === t2.name) { + return 0; + } + return 1; + }); + + callback(null, _.map(terms, function (t, i) { + t.insertValue = t.insertValue || t.value; + t.value = '' + t.value; // normalize to strings + t.score = -i; + return t; + })); + } + } + catch (e) { + console.log('error while getting completion terms', e); + callback(e, null); + } + } + + addChangeListener(); + + // Hook into Ace + + // disable standard context based autocompletion. + ace.define('ace/autocomplete/text_completer', ['require', 'exports', 'module'], function (require, exports) { + exports.getCompletions = function (editor, session, pos, prefix, callback) { + callback(null, []); + }; + }); + + const langTools = ace.acequire('ace/ext/language_tools'); + + langTools.setCompleters([{ + identifierRegexps: [ + /[a-zA-Z_0-9\.\$\-\u00A2-\uFFFF]/ // adds support for dot character + ], + getCompletions: getCompletions + }]); + + editor.setOptions({ + enableBasicAutocompletion: true + }); + editor.$blockScrolling = Infinity; + return { + + _test: { + getCompletions: getCompletions, + addReplacementInfoToContext: addReplacementInfoToContext, + addChangeListener: addChangeListener, + removeChangeListener: removeChangeListener + } + }; +} diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/body_completer.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/body_completer.js similarity index 95% rename from src/legacy/core_plugins/console/public/src/autocomplete/body_completer.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/body_completer.js index 68e0889f9c618..e377a749aaf78 100644 --- a/src/legacy/core_plugins/console/public/src/autocomplete/body_completer.js +++ b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/body_completer.js @@ -127,6 +127,18 @@ class ScopeResolver extends SharedComponent { } function getTemplate(description) { if (description.__template) { + if (description.__raw && _.isString(description.__template)) { + return { + // This is a special secret attribute that gets passed through to indicate that + // the raw value should be passed through to the console without JSON.stringifying it + // first. + // + // Primary use case is to allow __templates to contain extended JSON special values like + // triple quotes. + __raw: true, + value: description.__template, + }; + } return description.__template; } else if (description.__one_of) { return getTemplate(description.__one_of[0]); diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/accept_endpoint_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/accept_endpoint_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/accept_endpoint_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/accept_endpoint_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/autocomplete_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/autocomplete_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/autocomplete_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/autocomplete_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/conditional_proxy.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/conditional_proxy.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/conditional_proxy.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/conditional_proxy.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/constant_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/constant_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/constant_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/constant_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/field_autocomplete_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/field_autocomplete_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/field_autocomplete_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/field_autocomplete_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/global_only_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/global_only_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/global_only_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/global_only_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/id_autocomplete_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/id_autocomplete_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/id_autocomplete_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/id_autocomplete_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/index.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/index.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/index.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/index.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/index_autocomplete_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/index_autocomplete_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/index_autocomplete_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/index_autocomplete_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/list_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/list_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/list_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/list_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/object_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/object_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/object_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/object_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/shared_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/shared_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/shared_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/shared_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/simple_param_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/simple_param_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/simple_param_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/simple_param_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/template_autocomplete_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/template_autocomplete_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/template_autocomplete_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/template_autocomplete_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/type_autocomplete_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/type_autocomplete_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/type_autocomplete_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/type_autocomplete_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/url_pattern_matcher.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/url_pattern_matcher.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/url_pattern_matcher.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/url_pattern_matcher.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/components/username_autocomplete_component.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/username_autocomplete_component.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/components/username_autocomplete_component.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/components/username_autocomplete_component.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/engine.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/engine.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/engine.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/engine.js diff --git a/src/legacy/core_plugins/console/public/src/autocomplete/url_params.js b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete/url_params.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/autocomplete/url_params.js rename to src/legacy/core_plugins/console/public/quarantined/src/autocomplete/url_params.js diff --git a/src/legacy/core_plugins/console/public/src/curl.js b/src/legacy/core_plugins/console/public/quarantined/src/curl.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/curl.js rename to src/legacy/core_plugins/console/public/quarantined/src/curl.js diff --git a/src/legacy/core_plugins/console/public/src/directives/_help.scss b/src/legacy/core_plugins/console/public/quarantined/src/directives/_help.scss similarity index 100% rename from src/legacy/core_plugins/console/public/src/directives/_help.scss rename to src/legacy/core_plugins/console/public/quarantined/src/directives/_help.scss diff --git a/src/legacy/core_plugins/console/public/quarantined/src/directives/_history.scss b/src/legacy/core_plugins/console/public/quarantined/src/directives/_history.scss new file mode 100644 index 0000000000000..efd72245b3c48 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/directives/_history.scss @@ -0,0 +1,40 @@ +@import 'src/legacy/ui/public/styles/_styling_constants'; + +.conHistory { + @include euiBottomShadow; + padding: $euiSizeM; +} + +.conHistory__body { + display: flex; + height: $euiSizeXL * 10; + > ul { + margin-bottom: 0; + } +} + +.conHistory__body__spacer { + flex: 0 0 1%; +} + +.conHistory__reqs, +.conHistory__viewer { + flex: 0 0 49.5%; +} + +.conHistory__reqs { + overflow: auto; +} + +.conHistory__req { + display: flex; + justify-content: space-between; + + &-selected { + background-color: $euiColorLightestShade; + } +} + +.conHistory__reqIcon { + color: $euiColorMediumShade; +} diff --git a/src/legacy/core_plugins/console/public/src/directives/_index.scss b/src/legacy/core_plugins/console/public/quarantined/src/directives/_index.scss similarity index 100% rename from src/legacy/core_plugins/console/public/src/directives/_index.scss rename to src/legacy/core_plugins/console/public/quarantined/src/directives/_index.scss diff --git a/src/legacy/core_plugins/console/public/src/es.js b/src/legacy/core_plugins/console/public/quarantined/src/es.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/es.js rename to src/legacy/core_plugins/console/public/quarantined/src/es.js diff --git a/src/legacy/core_plugins/console/public/quarantined/src/input.js b/src/legacy/core_plugins/console/public/quarantined/src/input.js new file mode 100644 index 0000000000000..89672a5823ad5 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/input.js @@ -0,0 +1,200 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Autocomplete from './autocomplete'; +import mappings from './mappings'; +const SenseEditor = require('./sense_editor/editor'); +const utils = require('./utils'); +const es = require('./es'); + +let input; +export function initializeInput($el, $actionsEl, history, settings) { + input = new SenseEditor($el); + + input.autocomplete = new Autocomplete(input); + + input.$actions = $actionsEl; + + /** + * Setup the "send" shortcut + */ + + let CURRENT_REQ_ID = 0; + + function sendCurrentRequestToES(addedToHistoryCb, output) { + const reqId = ++CURRENT_REQ_ID; + + input.getRequestsInRange(requests => { + if (reqId !== CURRENT_REQ_ID) { + return; + } + if (output) { + output.update(''); + } + + if (requests.length === 0) { + return; + } + + const isMultiRequest = requests.length > 1; + const finishChain = () => { + /* noop */ + }; + + let isFirstRequest = true; + + const sendNextRequest = () => { + if (reqId !== CURRENT_REQ_ID) { + return; + } + if (requests.length === 0) { + finishChain(); + return; + } + const req = requests.shift(); + const esPath = req.url; + const esMethod = req.method; + let esData = utils.collapseLiteralStrings(req.data.join('\n')); + if (esData) { + esData += '\n'; + } //append a new line for bulk requests. + + es.send(esMethod, esPath, esData).always((dataOrjqXHR, textStatus, jqXhrORerrorThrown) => { + if (reqId !== CURRENT_REQ_ID) { + return; + } + + const xhr = dataOrjqXHR.promise ? dataOrjqXHR : jqXhrORerrorThrown; + + function modeForContentType(contentType) { + if (contentType.indexOf('text/plain') >= 0) { + return 'ace/mode/text'; + } else if (contentType.indexOf('application/yaml') >= 0) { + return 'ace/mode/yaml'; + } + return null; + } + + const isSuccess = + typeof xhr.status === 'number' && + // Things like DELETE index where the index is not there are OK. + ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 404); + + if (isSuccess) { + if (xhr.status !== 404 && settings.getPolling()) { + // If the user has submitted a request against ES, something in the fields, indices, aliases, + // or templates may have changed, so we'll need to update this data. Assume that if + // the user disables polling they're trying to optimize performance or otherwise + // preserve resources, so they won't want this request sent either. + mappings.retrieveAutoCompleteInfo(); + } + + // we have someone on the other side. Add to history + history.addToHistory(esPath, esMethod, esData); + if (addedToHistoryCb) { + addedToHistoryCb(); + } + + let value = xhr.responseText; + const mode = modeForContentType(xhr.getAllResponseHeaders('Content-Type') || ''); + + // Apply triple quotes to output. + if (settings.getTripleQuotes() && (mode === null || mode === 'application/json')) { + // assume json - auto pretty + try { + value = utils.expandLiteralStrings(value); + } catch (e) { + // nothing to do here + } + } + + const warnings = xhr.getResponseHeader('warning'); + if (warnings) { + const deprecationMessages = utils.extractDeprecationMessages(warnings); + value = deprecationMessages.join('\n') + '\n' + value; + } + + if (isMultiRequest) { + value = '# ' + req.method + ' ' + req.url + '\n' + value; + } + + if (output) { + if (isFirstRequest) { + output.update(value, mode); + } else { + output.append('\n' + value); + } + } + + isFirstRequest = false; + // single request terminate via sendNextRequest as well + sendNextRequest(); + } else { + let value; + let mode; + if (xhr.responseText) { + value = xhr.responseText; // ES error should be shown + mode = modeForContentType(xhr.getAllResponseHeaders('Content-Type') || ''); + if (value[0] === '{') { + try { + value = JSON.stringify(JSON.parse(value), null, 2); + } catch (e) { + // nothing to do here + } + } + } else { + value = 'Request failed to get to the server (status code: ' + xhr.status + ')'; + mode = 'ace/mode/text'; + } + if (isMultiRequest) { + value = '# ' + req.method + ' ' + req.url + '\n' + value; + } + if (output) { + if (isFirstRequest) { + output.update(value, mode); + } else { + output.append('\n' + value); + } + } + finishChain(); + } + }); + }; + + sendNextRequest(); + }); + } + + /** + * Init the editor + */ + if (settings) { + settings.applyCurrentSettings(input); + } + input.focus(); + input.highlightCurrentRequestsAndUpdateActionBar(); + + input.sendCurrentRequestToES = sendCurrentRequestToES; + + return input; +} + +export default function getInput() { + return input; +} diff --git a/src/legacy/core_plugins/console/public/src/kb.js b/src/legacy/core_plugins/console/public/quarantined/src/kb.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/kb.js rename to src/legacy/core_plugins/console/public/quarantined/src/kb.js diff --git a/src/legacy/core_plugins/console/public/src/kb/api.js b/src/legacy/core_plugins/console/public/quarantined/src/kb/api.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/kb/api.js rename to src/legacy/core_plugins/console/public/quarantined/src/kb/api.js diff --git a/src/legacy/core_plugins/console/public/src/mappings.js b/src/legacy/core_plugins/console/public/quarantined/src/mappings.js similarity index 96% rename from src/legacy/core_plugins/console/public/src/mappings.js rename to src/legacy/core_plugins/console/public/quarantined/src/mappings.js index 51864333ef1fe..4538b058c2d8b 100644 --- a/src/legacy/core_plugins/console/public/src/mappings.js +++ b/src/legacy/core_plugins/console/public/quarantined/src/mappings.js @@ -17,10 +17,11 @@ * under the License. */ +import { legacyBackDoorToSettings } from '../../../np_ready/public/application'; + const $ = require('jquery'); const _ = require('lodash'); const es = require('./es'); -const settings = require('./settings'); // NOTE: If this value ever changes to be a few seconds or less, it might introduce flakiness // due to timing issues in our app.js tests. @@ -257,7 +258,7 @@ function clear() { } function retrieveSettings(settingsKey, settingsToRetrieve) { - const currentSettings = settings.getAutocomplete(); + const currentSettings = legacyBackDoorToSettings().getAutocomplete(); const settingKeyToPathMap = { fields: '_mapping', indices: '_aliases', @@ -289,7 +290,7 @@ function retrieveSettings(settingsKey, settingsToRetrieve) { // unchanged alone (both selected and unselected). // 3. Poll: Use saved. Fetch selected. Ignore unselected. -function retrieveAutoCompleteInfo(settingsToRetrieve = settings.getAutocomplete()) { +function retrieveAutoCompleteInfo(settingsToRetrieve = legacyBackDoorToSettings().getAutocomplete()) { if (pollTimeoutId) { clearTimeout(pollTimeoutId); } @@ -329,7 +330,7 @@ function retrieveAutoCompleteInfo(settingsToRetrieve = settings.getAutocomplete( pollTimeoutId = setTimeout(() => { // This looks strange/inefficient, but it ensures correct behavior because we don't want to send // a scheduled request if the user turns off polling. - if (settings.getPolling()) { + if (legacyBackDoorToSettings().getPolling()) { retrieveAutoCompleteInfo(); } }, POLL_INTERVAL); diff --git a/src/legacy/core_plugins/console/public/quarantined/src/output.js b/src/legacy/core_plugins/console/public/quarantined/src/output.js new file mode 100644 index 0000000000000..d5ffe736e2dbe --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/output.js @@ -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 _ from 'lodash'; +const ace = require('brace'); +const OutputMode = require('./sense_editor/mode/output'); +const smartResize = require('./smart_resize'); + +let output; +export function initializeOutput($el, settings) { + output = ace.acequire('ace/ace').edit($el[0]); + + const outputMode = new OutputMode.Mode(); + + output.$blockScrolling = Infinity; + output.resize = smartResize(output); + output.update = (val, mode, cb) => { + if (typeof mode === 'function') { + cb = mode; + mode = void 0; + } + + const session = output.getSession(); + + session.setMode(val ? mode || outputMode : 'ace/mode/text'); + session.setValue(val); + if (typeof cb === 'function') { + setTimeout(cb); + } + }; + + output.append = (val, foldPrevious, cb) => { + if (typeof foldPrevious === 'function') { + cb = foldPrevious; + foldPrevious = true; + } + if (_.isUndefined(foldPrevious)) { + foldPrevious = true; + } + const session = output.getSession(); + const lastLine = session.getLength(); + if (foldPrevious) { + output.moveCursorTo(Math.max(0, lastLine - 1), 0); + } + session.insert({ row: lastLine, column: 0 }, '\n' + val); + output.moveCursorTo(lastLine + 1, 0); + if (typeof cb === 'function') { + setTimeout(cb); + } + }; + + output.$el = $el; + + // eslint-disable-next-line + (function setupSession(session) { + session.setMode('ace/mode/text'); + session.setFoldStyle('markbeginend'); + session.setTabSize(2); + session.setUseWrapMode(true); + })(output.getSession()); + + output.setShowPrintMargin(false); + output.setReadOnly(true); + + if (settings) { + settings.applyCurrentSettings(output); + } + + return output; +} + +export default function getOutput() { + return output; +} diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/editor.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/editor.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/editor.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/editor.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/input.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/input.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/input.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/input.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/input_highlight_rules.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/input_highlight_rules.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/input_highlight_rules.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/input_highlight_rules.js diff --git a/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/output.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/output.js new file mode 100644 index 0000000000000..e2598f2a73d77 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/output.js @@ -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 ace from 'brace'; +require('./output_highlight_rules'); + + +const oop = ace.acequire('ace/lib/oop'); +const JSONMode = ace.acequire('ace/mode/json').Mode; +const HighlightRules = require('./output_highlight_rules').OutputJsonHighlightRules; +const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; +const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour; +const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode; +ace.acequire('ace/worker/worker_client'); +const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer; + +export function Mode() { + this.$tokenizer = new AceTokenizer(new HighlightRules().getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +} +oop.inherits(Mode, JSONMode); + +(function () { + this.createWorker = function () { + return null; + }; + + this.$id = 'sense/mode/input'; +}).call(Mode.prototype); diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/output_highlight_rules.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/output_highlight_rules.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/output_highlight_rules.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/output_highlight_rules.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/script.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/script.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/script.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/script.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/script_highlight_rules.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/script_highlight_rules.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/script_highlight_rules.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/script_highlight_rules.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/worker/index.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/worker/index.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/worker/index.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/worker/index.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/worker/worker.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/worker/worker.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/worker/worker.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/worker/worker.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/x_json_highlight_rules.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/x_json_highlight_rules.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/mode/x_json_highlight_rules.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/mode/x_json_highlight_rules.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/row_parser.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/row_parser.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/row_parser.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/row_parser.js diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/theme-sense-dark.js b/src/legacy/core_plugins/console/public/quarantined/src/sense_editor/theme_sense_dark.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/sense_editor/theme-sense-dark.js rename to src/legacy/core_plugins/console/public/quarantined/src/sense_editor/theme_sense_dark.js diff --git a/src/legacy/core_plugins/console/public/src/smart_resize.js b/src/legacy/core_plugins/console/public/quarantined/src/smart_resize.js similarity index 100% rename from src/legacy/core_plugins/console/public/src/smart_resize.js rename to src/legacy/core_plugins/console/public/quarantined/src/smart_resize.js index 2cae2d7f17615..8ac5eda345c23 100644 --- a/src/legacy/core_plugins/console/public/src/smart_resize.js +++ b/src/legacy/core_plugins/console/public/quarantined/src/smart_resize.js @@ -21,8 +21,8 @@ import { get, throttle } from 'lodash'; export default function (editor) { const resize = editor.resize; - const throttledResize = throttle(() => { + const throttledResize = throttle(() => { resize.call(editor); // Keep current top line in view when resizing to avoid losing user context diff --git a/src/legacy/core_plugins/console/public/quarantined/src/utils.js b/src/legacy/core_plugins/console/public/quarantined/src/utils.js new file mode 100644 index 0000000000000..5b6bd1646c300 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/src/utils.js @@ -0,0 +1,141 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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'; + +const utils = {}; + +utils.textFromRequest = function (request) { + let data = request.data; + if (typeof data !== 'string') { + data = data.join('\n'); + } + return request.method + ' ' + request.url + '\n' + data; +}; + +utils.jsonToString = function (data, indent) { + return JSON.stringify(data, null, indent ? 2 : 0); +}; + +utils.reformatData = function (data, indent) { + let changed = false; + const formattedData = []; + for (let i = 0; i < data.length; i++) { + const curDoc = data[i]; + try { + let newDoc = utils.jsonToString(JSON.parse(utils.collapseLiteralStrings(curDoc)), indent ? 2 : 0); + if (indent) { + newDoc = utils.expandLiteralStrings(newDoc); + } + changed = changed || newDoc !== curDoc; + formattedData.push(newDoc); + } + catch (e) { + console.log(e); + formattedData.push(curDoc); + } + } + + return { + changed: changed, + data: formattedData + }; +}; + +utils.collapseLiteralStrings = function (data) { + const splitData = data.split(`"""`); + for (let idx = 1; idx < splitData.length - 1; idx += 2) { + splitData[idx] = JSON.stringify(splitData[idx]); + } + return splitData.join(''); +}; + +/* + The following regex describes global match on: + 1. one colon followed by any number of space characters + 2. one double quote (not escaped, special case for JSON in JSON). + 3. greedily match any non double quote and non newline char OR any escaped double quote char (non-capturing). + 4. handle a special case where an escaped slash may be the last character + 5. one double quote + + For instance: `: "some characters \" here"` + Will match and be expanded to: `"""some characters " here"""` + + */ + +const LITERAL_STRING_CANDIDATES = /((:[\s\r\n]*)([^\\])"(\\"|[^"\n])*\\?")/g; + +utils.expandLiteralStrings = function (data) { + return data.replace(LITERAL_STRING_CANDIDATES, function (match, string) { + // Expand to triple quotes if there are _any_ slashes + if (string.match(/\\./)) { + const firstDoubleQuoteIdx = string.indexOf('"'); + const colonAndAnySpacing = string.slice(0, firstDoubleQuoteIdx); + const rawStringifiedValue = string.slice(firstDoubleQuoteIdx, string.length); + const jsonValue = JSON.parse(rawStringifiedValue) + .replace('^\s*\n', '') + .replace('\n\s*^', ''); + return `${colonAndAnySpacing}"""${jsonValue}"""`; + } else { + return string; + } + }); +}; + +utils.extractDeprecationMessages = function (warnings) { + // pattern for valid warning header + const re = /\d{3} [0-9a-zA-Z!#$%&'*+-.^_`|~]+ \"((?:\t| |!|[\x23-\x5b]|[\x5d-\x7e]|[\x80-\xff]|\\\\|\\")*)\"(?: \"[^"]*\")?/; + // split on any comma that is followed by an even number of quotes + return _.map(utils.splitOnUnquotedCommaSpace(warnings), function (warning) { + const match = re.exec(warning); + // extract the actual warning if there was a match + return '#! Deprecation: ' + (match !== null ? utils.unescape(match[1]) : warning); + }); +}; + +utils.unescape = function (s) { + return s.replace(/\\\\/g, '\\').replace(/\\"/g, '"'); +}; + +utils.splitOnUnquotedCommaSpace = function (s) { + let quoted = false; + const arr = []; + let buffer = ''; + let i = 0; + while (i < s.length) { + let token = s.charAt(i++); + if (token === '\\' && i < s.length) { + token += s.charAt(i++); + } else if (token === ',' && i < s.length && s.charAt(i) === ' ') { + token += s.charAt(i++); + } + if (token === '"') { + quoted = !quoted; + } else if (!quoted && token === ', ') { + arr.push(buffer); + buffer = ''; + continue; + } + buffer += token; + } + arr.push(buffer); + return arr; +}; + +export default utils; diff --git a/src/legacy/core_plugins/console/public/tests/src/content_type.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/content_type.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/content_type.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/content_type.test.js diff --git a/src/legacy/core_plugins/console/public/tests/src/curl_parsing.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/curl_parsing.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/curl_parsing.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/curl_parsing.test.js diff --git a/src/legacy/core_plugins/console/public/tests/src/curl_parsing.txt b/src/legacy/core_plugins/console/public/quarantined/tests/src/curl_parsing.txt similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/curl_parsing.txt rename to src/legacy/core_plugins/console/public/quarantined/tests/src/curl_parsing.txt diff --git a/src/legacy/core_plugins/console/public/tests/src/editor.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/editor.test.js similarity index 99% rename from src/legacy/core_plugins/console/public/tests/src/editor.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/editor.test.js index ef1b1fb2dd65c..a356f8ff29cdc 100644 --- a/src/legacy/core_plugins/console/public/tests/src/editor.test.js +++ b/src/legacy/core_plugins/console/public/quarantined/tests/src/editor.test.js @@ -45,7 +45,8 @@ describe('Editor', () => { input = initializeInput( $('#ConAppEditor'), $('#ConAppEditorActions'), - $('#ConCopyAsCurl'), + {}, + { applyCurrentSettings: () => {} }, null ); input.$el.show(); diff --git a/src/legacy/core_plugins/console/public/tests/src/editor_input1.txt b/src/legacy/core_plugins/console/public/quarantined/tests/src/editor_input1.txt similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/editor_input1.txt rename to src/legacy/core_plugins/console/public/quarantined/tests/src/editor_input1.txt diff --git a/src/legacy/core_plugins/console/public/tests/src/input_tokenization.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/input_tokenization.test.js similarity index 97% rename from src/legacy/core_plugins/console/public/tests/src/input_tokenization.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/input_tokenization.test.js index 3c249a0c86bc5..7267956f57280 100644 --- a/src/legacy/core_plugins/console/public/tests/src/input_tokenization.test.js +++ b/src/legacy/core_plugins/console/public/quarantined/tests/src/input_tokenization.test.js @@ -39,10 +39,18 @@ describe('Input Tokenization', () => { input = initializeInput( $('#ConAppEditor'), $('#ConAppEditorActions'), - $('#ConCopyAsCurl'), + {}, + { applyCurrentSettings: () => {} }, + null + ); + + input = initializeInput( + $('#ConAppEditor'), + $('#ConAppEditorActions'), + {}, + { applyCurrentSettings: () => {} }, null ); - input = initializeInput($('#ConAppEditor'), $('#ConAppEditorActions'), $('#ConCopyAsCurl'), null); input.$el.show(); input.autocomplete._test.removeChangeListener(); }); diff --git a/src/legacy/core_plugins/console/public/tests/src/integration.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/integration.test.js similarity index 99% rename from src/legacy/core_plugins/console/public/tests/src/integration.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/integration.test.js index 0164f291594f3..5bd8fd4a5b4f5 100644 --- a/src/legacy/core_plugins/console/public/tests/src/integration.test.js +++ b/src/legacy/core_plugins/console/public/quarantined/tests/src/integration.test.js @@ -38,8 +38,9 @@ describe('Integration', () => { input = initializeInput( $('#ConAppEditor'), $('#ConAppEditorActions'), - $('#ConCopyAsCurl'), - null + {}, + { applyCurrentSettings: () => {} }, + null, ); input.$el.show(); input.autocomplete._test.removeChangeListener(); diff --git a/src/legacy/core_plugins/console/public/tests/src/kb.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/kb.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/kb.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/kb.test.js diff --git a/src/legacy/core_plugins/console/public/tests/src/mapping.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/mapping.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/mapping.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/mapping.test.js diff --git a/src/legacy/core_plugins/console/public/tests/src/output_tokenization.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/output_tokenization.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/output_tokenization.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/output_tokenization.test.js diff --git a/src/legacy/core_plugins/console/public/quarantined/tests/src/setup_mocks.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/setup_mocks.js new file mode 100644 index 0000000000000..e0a4a04638178 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/tests/src/setup_mocks.js @@ -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. + */ +/* eslint no-undef: 0 */ +jest.mock('../../src/sense_editor/mode/worker', () => { + return { workerModule: { id: 'sense_editor/mode/worker', src: '' } }; +}); +window.Worker = function () { + this.postMessage = () => {}; + this.terminate = () => {}; +}; +window.URL = { + createObjectURL: () => { + return ''; + }, +}; + +import 'brace'; +import 'brace/ext/language_tools'; +import 'brace/ext/searchbox'; +import 'brace/mode/json'; +import 'brace/mode/text'; + +jest.mock('../../../../np_ready/public/application', () => ({ legacyBackDoorToSettings: () => {}, })); + +document.queryCommandSupported = () => true; + +import jQuery from 'jquery'; +jest.spyOn(jQuery, 'ajax').mockImplementation( + () => + new Promise(() => { + // never resolve + }) +); diff --git a/src/legacy/core_plugins/console/public/tests/src/url_autocomplete.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/url_autocomplete.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/url_autocomplete.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/url_autocomplete.test.js diff --git a/src/legacy/core_plugins/console/public/tests/src/url_params.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/url_params.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/url_params.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/url_params.test.js diff --git a/src/legacy/core_plugins/console/public/tests/src/utils.test.js b/src/legacy/core_plugins/console/public/quarantined/tests/src/utils.test.js similarity index 100% rename from src/legacy/core_plugins/console/public/tests/src/utils.test.js rename to src/legacy/core_plugins/console/public/quarantined/tests/src/utils.test.js diff --git a/src/legacy/core_plugins/console/public/tests/src/utils_string_collapsing.txt b/src/legacy/core_plugins/console/public/quarantined/tests/src/utils_string_collapsing.txt similarity index 85% rename from src/legacy/core_plugins/console/public/tests/src/utils_string_collapsing.txt rename to src/legacy/core_plugins/console/public/quarantined/tests/src/utils_string_collapsing.txt index 235151317377f..5ddd1b5a376fe 100644 --- a/src/legacy/core_plugins/console/public/tests/src/utils_string_collapsing.txt +++ b/src/legacy/core_plugins/console/public/quarantined/tests/src/utils_string_collapsing.txt @@ -8,11 +8,11 @@ to you """ ========== String only 2 ------------------------------------- -""" +""" starting with new lines and ending as well - """ +""" ------------------------------------- -"starting with new lines and ending as well" +"\nstarting with new lines and ending as well\n" ========== Strings in requests ------------------------------------- @@ -27,8 +27,8 @@ test2 } ------------------------------------- { - "f": { "somefield" : "test\ntest2" }, + "f": { "somefield" : "\ntest\ntest2\n" }, "g": { "script" : "second + \"\\\";" }, "h": 1, "script": "a + 2" -} \ No newline at end of file +} diff --git a/src/legacy/core_plugins/console/public/quarantined/tests/src/utils_string_expanding.txt b/src/legacy/core_plugins/console/public/quarantined/tests/src/utils_string_expanding.txt new file mode 100644 index 0000000000000..34bf0f3bc20e7 --- /dev/null +++ b/src/legacy/core_plugins/console/public/quarantined/tests/src/utils_string_expanding.txt @@ -0,0 +1,42 @@ +========== +Scripts in requests +------------------------------------- +{ + "f": { "script": { "source": "\ntest\ntest\\\\\\\\\\\\\\\\2\n" } }, + "g": { "script": "second + \"\\\";" }, + "a": "short with \\", + "\\\\h": 1, + "script": "a + 2" +} +------------------------------------- +{ + "f": { "script": { "source": """ +test +test\\\\\\\\2 +""" } }, + "g": { "script": """second + "\";""" }, + "a": """short with \""", + "\\\\h": 1, + "script": "a + 2" +} +========== +Preserve triple quotes +------------------------------------- +{ + "content\\\": "tri\"ple", +} +------------------------------------- +{ + "content\\\": """tri"ple""", +} +========== +Correctly parse with JSON embedded inside values +------------------------------------- +{ + "content\\\\": " { \"json\": \"inside\\\\\" ok! 1\n \" } " +} +------------------------------------- +{ + "content\\\\": """ { "json": "inside\\" ok! 1 + " } """ +} diff --git a/src/legacy/core_plugins/console/public/src/__tests__/app.js b/src/legacy/core_plugins/console/public/src/__tests__/app.js deleted file mode 100644 index 60c6f7a8ebb54..0000000000000 --- a/src/legacy/core_plugins/console/public/src/__tests__/app.js +++ /dev/null @@ -1,104 +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 $ from 'jquery'; - -import history from '../history'; -import mappings from '../mappings'; -import init from '../app'; - -describe('console app initialization', () => { - const sandbox = sinon.createSandbox(); - - let inputMock; - let outputMock; - let ajaxDoneStub; - beforeEach(() => { - ajaxDoneStub = sinon.stub(); - sandbox.stub($, 'ajax').returns({ done: ajaxDoneStub }); - sandbox.stub(history, 'getSavedEditorState'); - sandbox.stub(mappings, 'retrieveAutoCompleteInfo'); - - inputMock = { - update: sinon.stub(), - moveToNextRequestEdge: sinon.stub(), - highlightCurrentRequestsAndUpdateActionBar: sinon.stub(), - updateActionsBar: sinon.stub(), - getSession: sinon.stub().returns({ on() {} }) - }; - - outputMock = { - update: sinon.stub() - }; - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('correctly loads state from any external HTTPS links.', () => { - const mockContent = {}; - ajaxDoneStub.yields(mockContent); - - init(inputMock, outputMock, 'https://state.link.com/content'); - - sinon.assert.calledOnce($.ajax); - sinon.assert.calledWithExactly($.ajax, { - url: 'https://state.link.com/content', - dataType: 'text', - kbnXsrfToken: false - }); - - sinon.assert.calledTwice(inputMock.moveToNextRequestEdge); - sinon.assert.calledWithExactly(inputMock.moveToNextRequestEdge, true); - sinon.assert.calledOnce(inputMock.highlightCurrentRequestsAndUpdateActionBar); - sinon.assert.calledOnce(inputMock.updateActionsBar); - sinon.assert.calledOnce(inputMock.update); - sinon.assert.calledWithExactly(inputMock.update, sinon.match.same(mockContent)); - - sinon.assert.calledOnce(outputMock.update); - sinon.assert.calledWithExactly(outputMock.update, ''); - }); - - it('correctly loads state from GitHub API HTTPS links.', () => { - const mockContent = {}; - ajaxDoneStub.yields(mockContent); - - init(inputMock, outputMock, 'https://api.github.com/content'); - - sinon.assert.calledOnce($.ajax); - sinon.assert.calledWithExactly($.ajax, { - url: 'https://api.github.com/content', - dataType: 'text', - kbnXsrfToken: false, - headers: { Accept: 'application/vnd.github.v3.raw' } - }); - - sinon.assert.calledTwice(inputMock.moveToNextRequestEdge); - sinon.assert.calledWithExactly(inputMock.moveToNextRequestEdge, true); - sinon.assert.calledOnce(inputMock.highlightCurrentRequestsAndUpdateActionBar); - sinon.assert.calledOnce(inputMock.updateActionsBar); - sinon.assert.calledOnce(inputMock.update); - sinon.assert.calledWithExactly(inputMock.update, sinon.match.same(mockContent)); - - sinon.assert.calledOnce(outputMock.update); - sinon.assert.calledWithExactly(outputMock.update, ''); - }); -}); diff --git a/src/legacy/core_plugins/console/public/src/app.js b/src/legacy/core_plugins/console/public/src/app.js deleted file mode 100644 index c591de73d0056..0000000000000 --- a/src/legacy/core_plugins/console/public/src/app.js +++ /dev/null @@ -1,136 +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 $ = require('jquery'); - -const history = require('./history'); -const mappings = require('./mappings'); - -export default function init(input, output, sourceLocation = 'stored') { - $(document.body).removeClass('fouc'); - - // set the value of the input and clear the output - function resetToValues(content) { - if (content != null) { - input.update(content); - } - output.update(''); - } - - function setupAutosave() { - let timer; - const saveDelay = 500; - - input.getSession().on('change', function onChange() { - if (timer) { - timer = clearTimeout(timer); - } - timer = setTimeout(saveCurrentState, saveDelay); - }); - } - - function saveCurrentState() { - try { - const content = input.getValue(); - history.updateCurrentState(content); - } - catch (e) { - console.log('Ignoring saving error: ' + e); - } - } - function loadSavedState() { - const previousSaveState = history.getSavedEditorState(); - - if (sourceLocation === 'stored') { - if (previousSaveState) { - resetToValues(previousSaveState.content); - } - else { - resetToValues(); - input.autoIndent(); - } - } - else if (/^https?:\/\//.test(sourceLocation)) { - const loadFrom = { - url: sourceLocation, - // Having dataType here is required as it doesn't allow jQuery to `eval` content - // coming from the external source thereby preventing XSS attack. - dataType: 'text', - kbnXsrfToken: false - }; - - if (/https?:\/\/api.github.com/.test(sourceLocation)) { - loadFrom.headers = { Accept: 'application/vnd.github.v3.raw' }; - } - - $.ajax(loadFrom).done((data) => { - resetToValues(data); - input.moveToNextRequestEdge(true); - input.highlightCurrentRequestsAndUpdateActionBar(); - input.updateActionsBar(); - }); - } - else { - resetToValues(); - } - input.moveToNextRequestEdge(true); - } - - // stupid simple restore function, called when the user - // chooses to restore a request from the history - // PREVENTS history from needing to know about the input - history.restoreFromHistory = function applyHistoryElem(req) { - const session = input.getSession(); - let pos = input.getCursorPosition(); - let prefix = ''; - let suffix = '\n'; - if (input.parser.isStartRequestRow(pos.row)) { - pos.column = 0; - suffix += '\n'; - } - else if (input.parser.isEndRequestRow(pos.row)) { - const line = session.getLine(pos.row); - pos.column = line.length; - prefix = '\n\n'; - } - else if (input.parser.isInBetweenRequestsRow(pos.row)) { - pos.column = 0; - } - else { - pos = input.nextRequestEnd(pos); - prefix = '\n\n'; - } - - let s = prefix + req.method + ' ' + req.endpoint; - if (req.data) { - s += '\n' + req.data; - } - - s += suffix; - - session.insert(pos, s); - input.clearSelection(); - input.moveCursorTo(pos.row + prefix.length, 0); - input.focus(); - }; - - setupAutosave(); - loadSavedState(); - mappings.retrieveAutoCompleteInfo(); -} diff --git a/src/legacy/core_plugins/console/public/src/autocomplete.js b/src/legacy/core_plugins/console/public/src/autocomplete.js deleted file mode 100644 index 8275813ea2b98..0000000000000 --- a/src/legacy/core_plugins/console/public/src/autocomplete.js +++ /dev/null @@ -1,1000 +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 { - getTopLevelUrlCompleteComponents, - getEndpointBodyCompleteComponents, - getGlobalAutocompleteComponents, - getUnmatchedEndpointComponents -} from './kb'; -import utils from './utils'; -import { populateContext } from './autocomplete/engine'; -import { URL_PATH_END_MARKER } from './autocomplete/components'; -import _ from 'lodash'; -import ace from 'brace'; -import 'brace/ext/language_tools'; -import { i18n } from '@kbn/i18n'; - -const AceRange = ace.acequire('ace/range').Range; - -let LAST_EVALUATED_TOKEN = null; - -function isUrlParamsToken(token) { - switch ((token || {}).type) { - case 'url.param': - case 'url.equal': - case 'url.value': - case 'url.questionmark': - case 'url.amp': - return true; - default: - return false; - } -} -function getCurrentMethodAndTokenPaths(editor, pos, forceEndOfUrl) { - const tokenIter = editor.iterForPosition(pos.row, pos.column); - const startPos = pos; - let bodyTokenPath = []; - const ret = {}; - - const STATES = { - looking_for_key: 0, // looking for a key but without jumping over anything but white space and colon. - looking_for_scope_start: 1, // skip everything until scope start - start: 3 - }; - let state = STATES.start; - - // initialization problems - - let t = tokenIter.getCurrentToken(); - if (t) { - if (startPos.column === 0) { - // if we are at the beginning of the line, the current token is the one after cursor, not before which - // deviates from the standard. - t = tokenIter.stepBackward(); - state = STATES.looking_for_scope_start; - } - } - else { - if (startPos.column === 0) { - // empty lines do no have tokens, move one back - t = tokenIter.stepBackward(); - state = STATES.start; - } - } - - let walkedSomeBody = false; - - // climb one scope at a time and get the scope key - for (; t && t.type.indexOf('url') === -1 && t.type !== 'method'; t = tokenIter.stepBackward()) { - - if (t.type !== 'whitespace') { - walkedSomeBody = true; - } // marks we saw something - - switch (t.type) { - case 'variable': - if (state === STATES.looking_for_key) { - bodyTokenPath.unshift(t.value.trim().replace(/"/g, '')); - } - state = STATES.looking_for_scope_start; // skip everything until the beginning of this scope - break; - - case 'paren.lparen': - bodyTokenPath.unshift(t.value); - if (state === STATES.looking_for_scope_start) { - // found it. go look for the relevant key - state = STATES.looking_for_key; - } - break; - case 'paren.rparen': - // reset he search for key - state = STATES.looking_for_scope_start; - // and ignore this sub scope.. - let parenCount = 1; - t = tokenIter.stepBackward(); - while (t && parenCount > 0) { - switch (t.type) { - case 'paren.lparen': - parenCount--; - break; - case 'paren.rparen': - parenCount++; - break; - } - if (parenCount > 0) { - t = tokenIter.stepBackward(); - } - } - if (!t) // oops we run out.. we don't know what's up return null; - { - return {}; - } - continue; - case 'punctuation.end_triple_quote': - // reset the search for key - state = STATES.looking_for_scope_start; - for (t = tokenIter.stepBackward(); t; t = tokenIter.stepBackward()) { - if (t.type === 'punctuation.start_triple_quote') { - t = tokenIter.stepBackward(); - break; - } - } - if (!t) // oops we run out.. we don't know what's up return null; - { - return {}; - } - continue; - case 'punctuation.start_triple_quote': - if (state === STATES.start) { - state = STATES.looking_for_key; - } - else if (state === STATES.looking_for_key) { - state = STATES.looking_for_scope_start; - } - bodyTokenPath.unshift('"""'); - continue; - case 'string': - case 'constant.numeric': - case 'constant.language.boolean': - case 'text': - if (state === STATES.start) { - state = STATES.looking_for_key; - } - else if (state === STATES.looking_for_key) { - state = STATES.looking_for_scope_start; - } - - break; - case 'punctuation.comma': - if (state === STATES.start) { - state = STATES.looking_for_scope_start; - } - break; - case 'punctuation.colon': - case 'whitespace': - if (state === STATES.start) { - state = STATES.looking_for_key; - } - break; // skip white space - - } - } - - if (walkedSomeBody && (!bodyTokenPath || bodyTokenPath.length === 0)) { - // we had some content and still no path -> the cursor is position after a closed body -> no auto complete - return {}; - } - ret.urlTokenPath = []; - if (tokenIter.getCurrentTokenRow() === startPos.row) { - if (t && (t.type === 'url.part' || t.type === 'url.param' || t.type === 'url.value')) { - // we are forcing the end of the url for the purposes of determining an endpoint - if (forceEndOfUrl && t.type === 'url.part') { - ret.urlTokenPath.push(t.value); - ret.urlTokenPath.push(URL_PATH_END_MARKER); - } - // we are on the same line as cursor and dealing with a url. Current token is not part of the context - t = tokenIter.stepBackward(); - // This will force method parsing - while (t.type === 'whitespace') { - t = tokenIter.stepBackward(); - } - } - bodyTokenPath = null; // no not on a body line. - } - - ret.bodyTokenPath = bodyTokenPath; - - ret.urlParamsTokenPath = null; - ret.requestStartRow = tokenIter.getCurrentTokenRow(); - let curUrlPart; - - while (t && isUrlParamsToken(t)) { - switch (t.type) { - case 'url.value': - if (Array.isArray(curUrlPart)) { - curUrlPart.unshift(t.value); - } - else if (curUrlPart) { - curUrlPart = [t.value, curUrlPart]; - } - else { - curUrlPart = t.value; - } - break; - case 'url.comma': - if (!curUrlPart) { - curUrlPart = []; - } - else if (!Array.isArray(curUrlPart)) { - curUrlPart = [curUrlPart]; - } - break; - case 'url.param': - const v = curUrlPart; - curUrlPart = {}; - curUrlPart[t.value] = v; - break; - case 'url.amp': - case 'url.questionmark': - if (!ret.urlParamsTokenPath) { - ret.urlParamsTokenPath = []; - } - ret.urlParamsTokenPath.unshift(curUrlPart || {}); - curUrlPart = null; - break; - } - t = tokenIter.stepBackward(); - } - - curUrlPart = null; - while (t && t.type.indexOf('url') !== -1) { - switch (t.type) { - case 'url.part': - if (Array.isArray(curUrlPart)) { - curUrlPart.unshift(t.value); - } - else if (curUrlPart) { - curUrlPart = [t.value, curUrlPart]; - } - else { - curUrlPart = t.value; - } - break; - case 'url.comma': - if (!curUrlPart) { - curUrlPart = []; - } - else if (!Array.isArray(curUrlPart)) { - curUrlPart = [curUrlPart]; - } - break; - case 'url.slash': - if (curUrlPart) { - ret.urlTokenPath.unshift(curUrlPart); - curUrlPart = null; - } - break; - } - t = editor.parser.prevNonEmptyToken(tokenIter); - } - - if (curUrlPart) { - ret.urlTokenPath.unshift(curUrlPart); - } - - if (!ret.bodyTokenPath && !ret.urlParamsTokenPath) { - - if (ret.urlTokenPath.length > 0) { - // // started on the url, first token is current token - ret.otherTokenValues = ret.urlTokenPath[0]; - } - } - else { - // mark the url as completed. - ret.urlTokenPath.push(URL_PATH_END_MARKER); - } - - if (t && t.type === 'method') { - ret.method = t.value; - } - return ret; -} -export function getEndpointFromPosition(editor, pos) { - const context = { ...getCurrentMethodAndTokenPaths(editor, pos, true) }; - const components = getTopLevelUrlCompleteComponents(context.method); - populateContext(context.urlTokenPath, context, editor, true, components); - return context.endpoint; -} -export default function (editor) { - - function isUrlPathToken(token) { - switch ((token || {}).type) { - case 'url.slash': - case 'url.comma': - case 'url.part': - return true; - default: - return false; - } - } - - function addMetaToTermsList(list, meta, template) { - return _.map(list, function (t) { - if (typeof t !== 'object') { - t = { name: t }; - } - return _.defaults(t, { meta: meta, template: template }); - }); - } - - function applyTerm(term) { - const session = editor.getSession(); - - const context = term.context; - - // make sure we get up to date replacement info. - addReplacementInfoToContext(context, editor.getCursorPosition(), term.insertValue); - - let termAsString; - if (context.autoCompleteType === 'body') { - termAsString = typeof term.insertValue === 'string' ? '"' + term.insertValue + '"' : term.insertValue + ''; - if (term.insertValue === '[' || term.insertValue === '{') { - termAsString = ''; - } - } - else { - termAsString = term.insertValue + ''; - } - - let valueToInsert = termAsString; - let templateInserted = false; - if (context.addTemplate && !_.isUndefined(term.template) && !_.isNull(term.template)) { - const indentedTemplateLines = utils.jsonToString(term.template, true).split('\n'); - let currentIndentation = session.getLine(context.rangeToReplace.start.row); - currentIndentation = currentIndentation.match(/^\s*/)[0]; - for (let i = 1; i < indentedTemplateLines.length; i++) // skip first line - {indentedTemplateLines[i] = currentIndentation + indentedTemplateLines[i];} - - valueToInsert += ': ' + indentedTemplateLines.join('\n'); - templateInserted = true; - } - else { - templateInserted = true; - if (term.value === '[') { - valueToInsert += '[]'; - } - else if (term.value === '{') { - valueToInsert += '{}'; - } - else { - templateInserted = false; - } - } - - valueToInsert = context.prefixToAdd + valueToInsert + context.suffixToAdd; - - // disable listening to the changes we are making. - removeChangeListener(); - - if (context.rangeToReplace.start.column !== context.rangeToReplace.end.column) { - session.replace(context.rangeToReplace, valueToInsert); - } - else { - editor.insert(valueToInsert); - } - - editor.clearSelection(); // for some reason the above changes selection - - // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do. - let newPos = { - row: context.rangeToReplace.start.row, - column: context.rangeToReplace.start.column + termAsString.length + context.prefixToAdd.length - + (templateInserted ? 0 : context.suffixToAdd.length) - }; - - const tokenIter = editor.iterForPosition(newPos.row, newPos.column); - - if (context.autoCompleteType === 'body') { - // look for the next place stand, just after a comma, { - let nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { - case 'paren.rparen': - newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; - break; - case 'punctuation.colon': - nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - if ((nonEmptyToken || {}).type === 'paren.lparen') { - nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; - if (nonEmptyToken && nonEmptyToken.value.indexOf('"') === 0) { - newPos.column++; - } // don't stand on " - } - break; - case 'paren.lparen': - case 'punctuation.comma': - tokenIter.stepForward(); - newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; - break; - } - editor.moveCursorToPosition(newPos); - } - - // re-enable listening to typing - addChangeListener(); - } - - function getAutoCompleteContext(editor, session, pos) { - // deduces all the parameters need to position and insert the auto complete - const context = { - autoCompleteSet: null, // instructions for what can be here - endpoint: null, - urlPath: null, - method: null, - activeScheme: null, - editor: editor - }; - - // context.updatedForToken = session.getTokenAt(pos.row, pos.column); - // - // if (!context.updatedForToken) - // context.updatedForToken = { value: "", start: pos.column }; // empty line - // - // context.updatedForToken.row = pos.row; // extend - - context.autoCompleteType = getAutoCompleteType(pos); - switch (context.autoCompleteType) { - case 'path': - addPathAutoCompleteSetToContext(context, pos); - break; - case 'url_params': - addUrlParamsAutoCompleteSetToContext(context, pos); - break; - case 'method': - addMethodAutoCompleteSetToContext(context, pos); - break; - case 'body': - addBodyAutoCompleteSetToContext(context, pos); - break; - default: - return null; - } - - if (!context.autoCompleteSet) { - return null; // nothing to do.. - } - - addReplacementInfoToContext(context, pos); - - context.createdWithToken = _.clone(context.updatedForToken); - - return context; - } - - function getAutoCompleteType(pos) { - // return "method", "path" or "body" to determine auto complete type. - - let rowMode = editor.parser.getRowParseMode(); - - //noinspection JSBitwiseOperatorUsage - if (rowMode & editor.parser.MODE.IN_REQUEST) { - return 'body'; - } - //noinspection JSBitwiseOperatorUsage - if (rowMode & editor.parser.MODE.REQUEST_START) { - // on url path, url params or method. - const tokenIter = editor.iterForPosition(pos.row, pos.column); - let t = tokenIter.getCurrentToken(); - - while (t.type === 'url.comma') { - t = tokenIter.stepBackward(); - } - switch (t.type) { - case 'method': - return 'method'; - case 'whitespace': - t = editor.parser.prevNonEmptyToken(tokenIter); - - switch ((t || {}).type) { - case 'method': - // we moved one back - return 'path'; - break; - default: - if (isUrlPathToken(t)) { - return 'path'; - } - if (isUrlParamsToken(t)) { - return 'url_params'; - } - return null; - } - break; - default: - if (isUrlPathToken(t)) { - return 'path'; - } - if (isUrlParamsToken(t)) { - return 'url_params'; - } - return null; - } - } - - // after start to avoid single line url only requests - //noinspection JSBitwiseOperatorUsage - if (rowMode & editor.parser.MODE.REQUEST_END) { - return 'body'; - } - - // in between request on an empty - if ((editor.getSession().getLine(pos.row) || '').trim() === '') { - // check if the previous line is a single line begging of a new request - rowMode = editor.parser.getRowParseMode(pos.row - 1); - //noinspection JSBitwiseOperatorUsage - if ((rowMode & editor.parser.MODE.REQUEST_START) && (rowMode & editor.parser.MODE.REQUEST_END)) { - return 'body'; - } - //o.w suggest a method - return 'method'; - } - - return null; - } - - function addReplacementInfoToContext(context, pos, replacingTerm) { - // extract the initial value, rangeToReplace & textBoxPosition - - // Scenarios for current token: - // - Nice token { "bla|" - // - Broken text token { bla| - // - No token : { | - // - Broken scenario { , bla| - // - Nice token, broken before: {, "bla" - - const session = editor.getSession(); - - context.updatedForToken = _.clone(session.getTokenAt(pos.row, pos.column)); - if (!context.updatedForToken) { - context.updatedForToken = { value: '', start: pos.column }; - } // empty line - - let anchorToken = context.createdWithToken; - if (!anchorToken) { - anchorToken = context.updatedForToken; - } - - switch (context.updatedForToken.type) { - case 'variable': - case 'string': - case 'text': - case 'constant.numeric': - case 'constant.language.boolean': - case 'method': - case 'url.index': - case 'url.type': - case 'url.id': - case 'url.method': - case 'url.endpoint': - case 'url.part': - case 'url.param': - case 'url.value': - context.rangeToReplace = new AceRange( - pos.row, anchorToken.start, pos.row, - context.updatedForToken.start + context.updatedForToken.value.length - ); - context.replacingToken = true; - break; - default: - if (replacingTerm && context.updatedForToken.value === replacingTerm) { - context.rangeToReplace = new AceRange( - pos.row, anchorToken.start, pos.row, - context.updatedForToken.start + context.updatedForToken.value.length - ); - context.replacingToken = true; - } - else { - // standing on white space, quotes or another punctuation - no replacing - context.rangeToReplace = new AceRange( - pos.row, pos.column, pos.row, pos.column - ); - context.replacingToken = false; - } - break; - } - - context.textBoxPosition = { row: context.rangeToReplace.start.row, column: context.rangeToReplace.start.column }; - - switch (context.autoCompleteType) { - case 'path': - addPathPrefixSuffixToContext(context); - break; - case 'url_params': - addUrlParamsPrefixSuffixToContext(context); - break; - case 'method': - addMethodPrefixSuffixToContext(context); - break; - case 'body': - addBodyPrefixSuffixToContext(context); - break; - } - } - - function addBodyPrefixSuffixToContext(context) { - // Figure out what happens next to the token to see whether it needs trailing commas etc. - - // Templates will be used if not destroying existing structure. - // -> token : {} or token ]/} or token , but not token : SOMETHING ELSE - - context.prefixToAdd = ''; - context.suffixToAdd = ''; - - let tokenIter = editor.iterForCurrentLoc(); - let nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { - case 'NOTOKEN': - case 'paren.lparen': - case 'paren.rparen': - case 'punctuation.comma': - context.addTemplate = true; - break; - case 'punctuation.colon': - // test if there is an empty object - if so we replace it - context.addTemplate = false; - - nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - if (!(nonEmptyToken && nonEmptyToken.value === '{')) { - break; - } - nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - if (!(nonEmptyToken && nonEmptyToken.value === '}')) { - break; - } - context.addTemplate = true; - // extend range to replace to include all up to token - context.rangeToReplace.end.row = tokenIter.getCurrentTokenRow(); - context.rangeToReplace.end.column = tokenIter.getCurrentTokenColumn() + nonEmptyToken.value.length; - - // move one more time to check if we need a trailing comma - nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { - case 'NOTOKEN': - case 'paren.rparen': - case 'punctuation.comma': - case 'punctuation.colon': - break; - default: - context.suffixToAdd = ', '; - } - - break; - default: - context.addTemplate = true; - context.suffixToAdd = ', '; - break; // for now play safe and do nothing. May be made smarter. - } - - // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do. - tokenIter = editor.iterForCurrentLoc(); - nonEmptyToken = tokenIter.getCurrentToken(); - let insertingRelativeToToken; // -1 is before token, 0 middle, +1 after token - if (context.replacingToken) { - insertingRelativeToToken = 0; - } - else { - const pos = editor.getCursorPosition(); - if (pos.column === context.updatedForToken.start) { - insertingRelativeToToken = -1; - } - else if (pos.column < context.updatedForToken.start + context.updatedForToken.value.length) { - insertingRelativeToToken = 0; - } - else { - insertingRelativeToToken = 1; - } - - } - // we should actually look at what's happening before this token - if (editor.parser.isEmptyToken(nonEmptyToken) || insertingRelativeToToken <= 0) { - nonEmptyToken = editor.parser.prevNonEmptyToken(tokenIter); - } - - switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { - case 'NOTOKEN': - case 'paren.lparen': - case 'punctuation.comma': - case 'punctuation.colon': - case 'method': - break; - default: - if (nonEmptyToken && nonEmptyToken.type.indexOf('url') < 0) { - context.prefixToAdd = ', '; - } - } - - return context; - } - - function addUrlParamsPrefixSuffixToContext(context) { - context.prefixToAdd = ''; - context.suffixToAdd = ''; - } - - function addMethodPrefixSuffixToContext(context) { - context.prefixToAdd = ''; - context.suffixToAdd = ''; - const tokenIter = editor.iterForCurrentLoc(); - const row = tokenIter.getCurrentTokenRow(); - const t = editor.parser.nextNonEmptyToken(tokenIter); - - if (tokenIter.getCurrentTokenRow() !== row || !t) { - // we still have nothing next to the method, add a space.. - context.suffixToAdd = ' '; - } - } - - function addPathPrefixSuffixToContext(context) { - context.prefixToAdd = ''; - context.suffixToAdd = ''; - } - - function addMethodAutoCompleteSetToContext(context) { - context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({ - name: m, - score: -i, - meta: i18n.translate('console.autocomplete.addMethodMetaText', { defaultMessage: 'method' }), - })); - } - - - function addPathAutoCompleteSetToContext(context, pos) { - const ret = getCurrentMethodAndTokenPaths(editor, pos); - context.method = ret.method; - context.token = ret.token; - context.otherTokenValues = ret.otherTokenValues; - context.urlTokenPath = ret.urlTokenPath; - const components = getTopLevelUrlCompleteComponents(context.method); - populateContext(ret.urlTokenPath, context, editor, true, components); - - - context.autoCompleteSet = addMetaToTermsList(context.autoCompleteSet, 'endpoint'); - } - - function addUrlParamsAutoCompleteSetToContext(context, pos) { - const ret = getCurrentMethodAndTokenPaths(editor, pos); - context.method = ret.method; - context.otherTokenValues = ret.otherTokenValues; - context.urlTokenPath = ret.urlTokenPath; - if (!ret.urlTokenPath) { // zero length tokenPath is true - - console.log('Can\'t extract a valid url token path.'); - return context; - } - - populateContext(ret.urlTokenPath, context, editor, false, getTopLevelUrlCompleteComponents(context.method)); - - if (!context.endpoint) { - console.log('couldn\'t resolve an endpoint.'); - return context; - } - - if (!ret.urlParamsTokenPath) { // zero length tokenPath is true - console.log('Can\'t extract a valid urlParams token path.'); - return context; - } - let tokenPath = []; - const currentParam = ret.urlParamsTokenPath.pop(); - if (currentParam) { - tokenPath = Object.keys(currentParam); // single key object - context.otherTokenValues = currentParam[tokenPath[0]]; - } - - populateContext(tokenPath, context, editor, true, - context.endpoint.paramsAutocomplete.getTopLevelComponents(context.method)); - return context; - } - - function addBodyAutoCompleteSetToContext(context, pos) { - - const ret = getCurrentMethodAndTokenPaths(editor, pos); - context.method = ret.method; - context.otherTokenValues = ret.otherTokenValues; - context.urlTokenPath = ret.urlTokenPath; - context.requestStartRow = ret.requestStartRow; - if (!ret.urlTokenPath) { // zero length tokenPath is true - console.log('Can\'t extract a valid url token path.'); - return context; - } - - populateContext(ret.urlTokenPath, context, editor, false, getTopLevelUrlCompleteComponents(context.method)); - - context.bodyTokenPath = ret.bodyTokenPath; - if (!ret.bodyTokenPath) { // zero length tokenPath is true - - console.log('Can\'t extract a valid body token path.'); - return context; - } - - // needed for scope linking + global term resolving - context.endpointComponentResolver = getEndpointBodyCompleteComponents; - context.globalComponentResolver = getGlobalAutocompleteComponents; - let components; - if (context.endpoint) { - components = context.endpoint.bodyAutocompleteRootComponents; - } - else { - components = getUnmatchedEndpointComponents(); - } - populateContext(ret.bodyTokenPath, context, editor, true, components); - - return context; - } - - - - const evaluateCurrentTokenAfterAChange = _.debounce(function evaluateCurrentTokenAfterAChange(pos) { - const session = editor.getSession(); - let currentToken = session.getTokenAt(pos.row, pos.column); - - if (!currentToken) { - if (pos.row === 0) { - LAST_EVALUATED_TOKEN = null; - return; - } - currentToken = { start: 0, value: '' }; // empty row - } - - currentToken.row = pos.row; // extend token with row. Ace doesn't supply it by default - if (editor.parser.isEmptyToken(currentToken)) { - // empty token. check what's coming next - const nextToken = session.getTokenAt(pos.row, pos.column + 1); - if (editor.parser.isEmptyToken(nextToken)) { - // Empty line, or we're not on the edge of current token. Save the current position as base - currentToken.start = pos.column; - LAST_EVALUATED_TOKEN = currentToken; - } - else { - nextToken.row = pos.row; - LAST_EVALUATED_TOKEN = nextToken; - } - return; - } - - if (!LAST_EVALUATED_TOKEN) { - LAST_EVALUATED_TOKEN = currentToken; - return; // wait for the next typing. - } - - if (LAST_EVALUATED_TOKEN.start !== currentToken.start || LAST_EVALUATED_TOKEN.row !== currentToken.row - || LAST_EVALUATED_TOKEN.value === currentToken.value) { - // not on the same place or nothing changed, cache and wait for the next time - LAST_EVALUATED_TOKEN = currentToken; - return; - } - - // don't automatically open the auto complete if some just hit enter (new line) or open a parentheses - switch (currentToken.type || 'UNKNOWN') { - case 'paren.lparen': - case 'paren.rparen': - case 'punctuation.colon': - case 'punctuation.comma': - case 'UNKNOWN': - return; - } - - LAST_EVALUATED_TOKEN = currentToken; - editor.execCommand('startAutocomplete'); - }, 100); - - function editorChangeListener() { - const cursor = editor.selection.lead; - if (editor.__ace.completer && editor.__ace.completer.activated) { - return; - } - evaluateCurrentTokenAfterAChange(cursor); - } - - function addChangeListener() { - editor.on('changeSelection', editorChangeListener); - } - - function removeChangeListener() { - editor.off('changeSelection', editorChangeListener); - } - - function getCompletions(aceEditor, session, pos, prefix, callback) { - try { - - const context = getAutoCompleteContext(editor, session, pos); - if (!context) { - callback(null, []); - } - else { - const terms = _.map(context.autoCompleteSet, function (term) { - if (typeof term !== 'object') { - term = { - name: term - }; - } else { - term = _.clone(term); - } - const defaults = { - value: term.name, - meta: 'API', - score: 0, - context: context, - }; - // we only need out custom insertMatch behavior for the body - if (context.autoCompleteType === 'body') { - defaults.completer = { - insertMatch: function () { - return applyTerm(term); - } - }; - } - return _.defaults(term, defaults); - }); - - terms.sort(function (t1, t2) { - /* score sorts from high to low */ - if (t1.score > t2.score) { - return -1; - } - if (t1.score < t2.score) { - return 1; - } - /* names sort from low to high */ - if (t1.name < t2.name) { - return -1; - } - if (t1.name === t2.name) { - return 0; - } - return 1; - }); - - callback(null, _.map(terms, function (t, i) { - t.insertValue = t.insertValue || t.value; - t.value = '' + t.value; // normalize to strings - t.score = -i; - return t; - })); - } - } - catch (e) { - console.log('error while getting completion terms', e); - callback(e, null); - } - } - - addChangeListener(); - - // Hook into Ace - - // disable standard context based autocompletion. - ace.define('ace/autocomplete/text_completer', ['require', 'exports', 'module'], function (require, exports) { - exports.getCompletions = function (editor, session, pos, prefix, callback) { - callback(null, []); - }; - }); - - const langTools = ace.acequire('ace/ext/language_tools'); - - langTools.setCompleters([{ - identifierRegexps: [ - /[a-zA-Z_0-9\.\$\-\u00A2-\uFFFF]/ // adds support for dot character - ], - getCompletions: getCompletions - }]); - - editor.setOptions({ - enableBasicAutocompletion: true - }); - editor.$blockScrolling = Infinity; - return { - - _test: { - getCompletions: getCompletions, - addReplacementInfoToContext: addReplacementInfoToContext, - addChangeListener: addChangeListener, - removeChangeListener: removeChangeListener - } - }; -} diff --git a/src/legacy/core_plugins/console/public/src/components/console_menu.js b/src/legacy/core_plugins/console/public/src/components/console_menu.js deleted file mode 100644 index 3ab05556f643e..0000000000000 --- a/src/legacy/core_plugins/console/public/src/components/console_menu.js +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import PropTypes from 'prop-types'; - -import React, { - Component, -} from 'react'; - -import { - EuiButtonIcon, - EuiContextMenuPanel, - EuiContextMenuItem, - EuiPopover, -} from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n/react'; - -export class ConsoleMenu extends Component { - constructor(props) { - super(props); - - this.state = { - curlCode: '', - isPopoverOpen: false, - }; - } - - mouseEnter = () => { - if (this.state.isPopoverOpen) return; - this.props.getCurl(text => { - this.setState({ curlCode: text }); - }); - } - - copyAsCurl() { - this.copyText(this.state.curlCode); - } - - copyText(text) { - const textField = document.createElement('textarea'); - textField.innerText = text; - document.body.appendChild(textField); - textField.select(); - document.execCommand('copy'); - textField.remove(); - } - - onButtonClick = () => { - this.setState(prevState => ({ - isPopoverOpen: !prevState.isPopoverOpen, - })); - }; - - closePopover = () => { - this.setState({ - isPopoverOpen: false, - }); - }; - - openDocs = () => { - this.closePopover(); - this.props.getDocumentation(); - this.props.openDocumentation(); - } - - render() { - const button = ( - - } - /> - ); - - const items = [ - ( - { this.closePopover(); this.copyAsCurl(); }} - > - - - ), ( - { this.openDocs(); }} - > - - - ), ( - { this.closePopover(); this.props.autoIndent(event); }} - > - - - ) - ]; - - return ( - - - - - - ); - } -} - -ConsoleMenu.propTypes = { - getCurl: PropTypes.func.isRequired, - openDocumentation: PropTypes.func.isRequired, - getDocumentation: PropTypes.func.isRequired, - autoIndent: PropTypes.func.isRequired, -}; diff --git a/src/legacy/core_plugins/console/public/src/components/dev_tools_settings.ts b/src/legacy/core_plugins/console/public/src/components/dev_tools_settings.ts deleted file mode 100644 index f3fd1442ca90f..0000000000000 --- a/src/legacy/core_plugins/console/public/src/components/dev_tools_settings.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. - */ - -export interface DevToolsSettings { - fontSize: number; - wrapMode: boolean; - autocomplete: { - fields: boolean; - indices: boolean; - templates: boolean; - }; - polling: boolean; - tripleQuotes: boolean; -} diff --git a/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js b/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js deleted file mode 100644 index 2011f23d11cc6..0000000000000 --- a/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js +++ /dev/null @@ -1,137 +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 { docTitle } from 'ui/doc_title'; - -import { applyResizeCheckerToEditors } from '../sense_editor_resize'; -import $ from 'jquery'; -import { initializeInput } from '../input'; -import { initializeOutput } from '../output'; -import init from '../app'; -import { getEndpointFromPosition } from '../autocomplete'; -import { DOC_LINK_VERSION } from 'ui/documentation_links'; - -// welcome message -import { showWelcomePanel } from '../helpers/welcome_show_panel'; -import storage from '../storage'; - -import { getTopNavConfig } from '../helpers/get_top_nav'; - -const module = require('ui/modules').get('app/sense'); - -module.run(function ($rootScope) { - module.setupResizeCheckerForRootEditors = ($el, ...editors) => { - return applyResizeCheckerToEditors($rootScope, $el, ...editors); - }; -}); - -function showWelcomeMessageIfNeeded($scope) { - if (storage.get('version_welcome_shown') !== '@@SENSE_REVISION') { - const hideWelcomePanel = showWelcomePanel(); - $scope.$on('$destroy', () => { - hideWelcomePanel(); - }); - } -} - -module.controller('SenseController', function SenseController($scope, $timeout, $location, kbnUiAceKeyboardModeService) { - docTitle.change('Console'); - - showWelcomeMessageIfNeeded($scope); - - // Since we pass this callback via reactDirective into a react component, which has the function defined as required - // in it's prop types, we should set this initially (before it's set in the $timeout below). Without this line - // the component we pass this in will throw an propType validation error. - $scope.getRequestsAsCURL = () => ''; - - // We need to wait for these elements to be rendered before we can select them with jQuery - // and then initialize this app - let input; - let output; - $timeout(async () => { - output = initializeOutput($('#ConAppOutput')); - input = initializeInput($('#ConAppEditor'), $('#ConAppEditorActions'), $('#ConCopyAsCurl'), output, $scope.openDocumentation); - init(input, output, $location.search().load_from); - kbnUiAceKeyboardModeService.initialize($scope, $('#ConAppEditor')); - const session = input.getSession(); - session.getSelection().on('changeCursor', () => { - $scope.getDocumentation(); - }); - $scope.getDocumentation(); - - // expose method for React Consumption - $scope.getRequestsAsCURL = input.getRequestsAsCURL; - }); - $scope.getDocumentation = () => { - input.getRequestsInRange(function (requests) { - if (!requests || requests.length === 0) { - $scope.documentation = null; - $scope.$apply(); - return; - } - const position = requests[0].range.end; - position.column = position.column - 1; - const endpoint = getEndpointFromPosition(input, position); - if (endpoint - && endpoint.documentation - && endpoint.documentation.indexOf('http') !== -1) { - $scope.documentation = endpoint.documentation.replace('/master/', `/${DOC_LINK_VERSION}/`); - $scope.documentation = $scope.documentation.replace('/current/', `/${DOC_LINK_VERSION}/`); - $scope.$apply(); - } else { - $scope.documentation = null; - $scope.$apply(); - } - }); - }; - - $scope.showHistory = false; - $scope.historyDirty = undefined; - $scope.toggleHistory = () => { - $scope.showHistory = !$scope.showHistory; - }; - - $scope.closeHistory = () => { - $scope.showHistory = false; - }; - - $scope.topNavMenu = getTopNavConfig($scope, $scope.toggleHistory); - - $scope.openDocumentation = () => { - if (!$scope.documentation) { - return; - } - window.open($scope.documentation, '_blank'); - }; - - $scope.sendSelected = () => { - input.focus(); - input.sendCurrentRequestToES(() => { - // History watches this value and will re-render itself when it changes, so that - // the list of requests stays up-to-date as new requests are sent. - $scope.lastRequestTimestamp = new Date().getTime(); - }); - return false; - }; - - $scope.autoIndent = (event) => { - input.autoIndent(); - event.preventDefault(); - input.focus(); - }; -}); diff --git a/src/legacy/core_plugins/console/public/src/directives/_history.scss b/src/legacy/core_plugins/console/public/src/directives/_history.scss deleted file mode 100644 index 1d13d366eec08..0000000000000 --- a/src/legacy/core_plugins/console/public/src/directives/_history.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import 'src/legacy/ui/public/styles/_styling_constants'; - -.conHistory { - @include euiBottomShadow; - padding: $euiSizeM; -} - -.conHistory__body { - display: flex; - height: $euiSizeXL * 10; -} - - -.conHistory__footer { - display: flex; - justify-content: space-between; - padding-top: $euiSize; -} - -.conHistory__footerButtonsRight { - text-align: right; -} - -.conHistory__reqs, -.conHistory__viewer { - flex: 0 0 50%; -} - -.conHistory__reqs { - overflow: auto; - margin-right: $euiSizeL; -} - -.conHistory__req { - display: flex; - justify-content: space-between; - - &-selected { - background-color: $euiColorLightestShade; - } -} - -.conHistory__reqIcon { - color: $euiColorMediumShade; -} diff --git a/src/legacy/core_plugins/console/public/src/directives/console_menu_directive.js b/src/legacy/core_plugins/console/public/src/directives/console_menu_directive.js deleted file mode 100644 index be04e6bcc17fe..0000000000000 --- a/src/legacy/core_plugins/console/public/src/directives/console_menu_directive.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 'ngreact'; - -import { wrapInI18nContext } from 'ui/i18n'; -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/sense', ['react']); - -import { ConsoleMenu } from '../components/console_menu'; - -module.directive('consoleMenu', function (reactDirective) { - return reactDirective(wrapInI18nContext(ConsoleMenu)); -}); diff --git a/src/legacy/core_plugins/console/public/src/directives/history.html b/src/legacy/core_plugins/console/public/src/directives/history.html deleted file mode 100644 index 4c3adebb54ea9..0000000000000 --- a/src/legacy/core_plugins/console/public/src/directives/history.html +++ /dev/null @@ -1,64 +0,0 @@ -
    -

    - -
    -
      -
    • - {{ history.describeReq(req) }} - -
    • -
    - - -
    - - -
    diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_history.js b/src/legacy/core_plugins/console/public/src/directives/sense_history.js deleted file mode 100644 index 29ad60a84e740..0000000000000 --- a/src/legacy/core_plugins/console/public/src/directives/sense_history.js +++ /dev/null @@ -1,105 +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 { keyCodes } from '@elastic/eui'; -import template from './history.html'; - -const { memoize } = require('lodash'); -const moment = require('moment'); - -const history = require('../history'); -require('./sense_history_viewer'); - -require('ui/modules') - .get('app/sense') - .directive('senseHistory', function () { - return { - restrict: 'E', - template, - controllerAs: 'history', - scope: { - isShown: '=', - historyDirty: '=', - close: '&', - }, - controller: function ($scope, $element) { - $scope.$watch('historyDirty', () => { - this.init(); - }); - - $scope.$watch('isShown', () => { - if ($scope.isShown) this.init(); - }); - - this.init = () => { - this.reqs = history.getHistory(); - this.selectedIndex = 0; - this.selectedReq = this.reqs[this.selectedIndex]; - this.viewingReq = this.selectedReq; - - // calculate the text description of a request - this.describeReq = memoize((req) => { - const endpoint = req.endpoint; - const date = moment(req.time); - - let formattedDate = date.format('MMM D'); - if (date.diff(moment(), 'days') > -7) { - formattedDate = date.fromNow(); - } - - return `${endpoint} (${formattedDate})`; - }); - this.describeReq.cache = new WeakMap(); - }; - - // main actions - this.clear = () => { - history.clearHistory($element); - this.init(); - }; - - this.close = () => { - $scope.close(); - }; - - this.restore = (req = this.selectedReq) => { - history.restoreFromHistory(req); - }; - - this.onKeyDown = (ev) => { - if (ev.keyCode === keyCodes.ENTER) { - this.restore(); - return; - } - - if (ev.keyCode === keyCodes.UP) { - ev.preventDefault(); - this.selectedIndex--; - } else if (ev.keyCode === keyCodes.DOWN) { - ev.preventDefault(); - this.selectedIndex++; - } - - this.selectedIndex = Math.min(Math.max(0, this.selectedIndex), this.reqs.length - 1); - this.selectedReq = this.reqs[this.selectedIndex]; - this.viewingReq = this.reqs[this.selectedIndex]; - }; - } - }; - }); diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_history_viewer.js b/src/legacy/core_plugins/console/public/src/directives/sense_history_viewer.js deleted file mode 100644 index e066605a2ca83..0000000000000 --- a/src/legacy/core_plugins/console/public/src/directives/sense_history_viewer.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const SenseEditor = require('../sense_editor/editor'); - -import { i18n } from '@kbn/i18n'; - -import { applyResizeCheckerToEditors } from '../sense_editor_resize'; - -require('ui/modules') - .get('app/sense') - .directive('senseHistoryViewer', function () { - return { - restrict: 'E', - scope: { - req: '=', - }, - link: function ($scope, $el) { - const viewer = new SenseEditor($el); - viewer.setReadOnly(true); - viewer.renderer.setShowPrintMargin(false); - applyResizeCheckerToEditors($scope, $el, viewer); - require('../settings').applyCurrentSettings(viewer); - - $scope.$watch('req', function (req) { - if (req) { - const s = req.method + ' ' + req.endpoint + '\n' + (req.data || ''); - viewer.setValue(s); - viewer.clearSelection(); - } else { - viewer.getSession().setValue( - i18n.translate('console.historyPage.noHistoryTextMessage', { defaultMessage: 'No history available' }) - ); - } - }); - - $scope.$on('$destroy', function () { - viewer.destroy(); - }); - } - }; - }); diff --git a/src/legacy/core_plugins/console/public/src/helpers/help_show_panel.tsx b/src/legacy/core_plugins/console/public/src/helpers/help_show_panel.tsx deleted file mode 100644 index a57fc92e17141..0000000000000 --- a/src/legacy/core_plugins/console/public/src/helpers/help_show_panel.tsx +++ /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 React from 'react'; -import ReactDOM from 'react-dom'; -import { I18nContext } from 'ui/i18n'; -import { HelpPanel } from '../components/help_panel'; - -let isOpen = false; - -export function showHelpPanel(): () => void { - const onClose = () => { - if (!container) return; - ReactDOM.unmountComponentAtNode(container); - isOpen = false; - }; - - const container = document.getElementById('consoleHelpPanel'); - - if (container && !isOpen) { - isOpen = true; - const element = ( - - - - ); - ReactDOM.render(element, container); - } - - return onClose; -} diff --git a/src/legacy/core_plugins/console/public/src/helpers/settings_show_modal.tsx b/src/legacy/core_plugins/console/public/src/helpers/settings_show_modal.tsx deleted file mode 100644 index c4f36d836dfda..0000000000000 --- a/src/legacy/core_plugins/console/public/src/helpers/settings_show_modal.tsx +++ /dev/null @@ -1,103 +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 { I18nContext } from 'ui/i18n'; -import React from 'react'; -import ReactDOM from 'react-dom'; -import { DevToolsSettingsModal, AutocompleteOptions } from '../components/settings_modal'; -import { DevToolsSettings } from '../components/dev_tools_settings'; - -// @ts-ignore -import mappings from '../mappings'; -// @ts-ignore -import { getCurrentSettings, updateSettings } from '../settings'; - -export function showSettingsModal() { - const container = document.getElementById('consoleSettingsModal'); - const curSettings = getCurrentSettings(); - - const refreshAutocompleteSettings = (selectedSettings: any) => { - mappings.retrieveAutoCompleteInfo(selectedSettings); - }; - - const closeModal = () => { - if (!container) return; - ReactDOM.unmountComponentAtNode(container); - container.innerHTML = ''; - }; - - const getAutocompleteDiff = (newSettings: DevToolsSettings, prevSettings: DevToolsSettings) => { - return Object.keys(newSettings.autocomplete).filter(key => { - // @ts-ignore - return prevSettings.autocomplete[key] !== newSettings.autocomplete[key]; - }); - }; - - const fetchAutocompleteSettingsIfNeeded = ( - newSettings: DevToolsSettings, - prevSettings: DevToolsSettings - ) => { - // We'll only retrieve settings if polling is on. The expectation here is that if the user - // disables polling it's because they want manual control over the fetch request (possibly - // because it's a very expensive request given their cluster and bandwidth). In that case, - // they would be unhappy with any request that's sent automatically. - if (newSettings.polling) { - const autocompleteDiff = getAutocompleteDiff(newSettings, prevSettings); - - const isSettingsChanged = autocompleteDiff.length > 0; - const isPollingChanged = prevSettings.polling !== newSettings.polling; - - if (isSettingsChanged) { - // If the user has changed one of the autocomplete settings, then we'll fetch just the - // ones which have changed. - const changedSettings: any = autocompleteDiff.reduce( - (changedSettingsAccum: any, setting: string): any => { - changedSettingsAccum[setting] = - newSettings.autocomplete[setting as AutocompleteOptions]; - return changedSettingsAccum; - }, - {} - ); - mappings.retrieveAutoCompleteInfo(changedSettings); - } else if (isPollingChanged) { - // If the user has turned polling on, then we'll fetch all selected autocomplete settings. - mappings.retrieveAutoCompleteInfo(); - } - } - }; - - const onSave = async (newSettings: DevToolsSettings) => { - const prevSettings = getCurrentSettings(); - updateSettings(newSettings); - fetchAutocompleteSettingsIfNeeded(newSettings, prevSettings); - closeModal(); - }; - - const element = ( - - - - ); - ReactDOM.render(element, container); -} diff --git a/src/legacy/core_plugins/console/public/src/helpers/welcome_show_panel.tsx b/src/legacy/core_plugins/console/public/src/helpers/welcome_show_panel.tsx deleted file mode 100644 index 60a66babef6e6..0000000000000 --- a/src/legacy/core_plugins/console/public/src/helpers/welcome_show_panel.tsx +++ /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 React from 'react'; -import ReactDOM from 'react-dom'; -import { I18nContext } from 'ui/i18n'; -import { WelcomePanel } from '../components/welcome_panel'; -// @ts-ignore -import storage from '../storage'; - -let isOpen = false; - -export function showWelcomePanel(): () => void { - const onClose = () => { - if (!container) return; - ReactDOM.unmountComponentAtNode(container); - isOpen = false; - }; - - const onDismiss = () => { - storage.set('version_welcome_shown', '@@SENSE_REVISION'); - onClose(); - }; - - const container = document.getElementById('consoleWelcomePanel'); - if (container && !isOpen) { - isOpen = true; - const element = ( - - - - ); - ReactDOM.render(element, container); - } - - return onClose; -} diff --git a/src/legacy/core_plugins/console/public/src/history.js b/src/legacy/core_plugins/console/public/src/history.js deleted file mode 100644 index 14d6ef5fcff04..0000000000000 --- a/src/legacy/core_plugins/console/public/src/history.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. - */ - -const $ = require('jquery'); -const storage = require('./storage'); - -const history = { - restoreFromHistory() { - // default method for history.restoreFromHistory - // replace externally to do something when the user chooses - // to relive a bit of history - throw new Error('not implemented'); - }, - - getHistoryKeys() { - return storage.keys() - .filter(key => key.indexOf('hist_elem') === 0) - .sort() - .reverse(); - }, - - getHistory() { - return history - .getHistoryKeys() - .map(key => storage.get(key)); - }, - - addToHistory(endpoint, method, data) { - const keys = history.getHistoryKeys(); - keys.splice(0, 500); // only maintain most recent X; - $.each(keys, function (i, k) { - storage.delete(k); - }); - - const timestamp = new Date().getTime(); - const k = 'hist_elem_' + timestamp; - storage.set(k, { - time: timestamp, - endpoint: endpoint, - method: method, - data: data - }); - }, - - updateCurrentState(content) { - const timestamp = new Date().getTime(); - storage.set('editor_state', { - time: timestamp, - content: content - }); - }, - - getSavedEditorState() { - const saved = storage.get('editor_state'); - if (!saved) return; - const { time, content } = saved; - return { time, content }; - }, - - clearHistory() { - history - .getHistoryKeys() - .forEach(key => storage.delete(key)); - } -}; - -export default history; diff --git a/src/legacy/core_plugins/console/public/src/input.js b/src/legacy/core_plugins/console/public/src/input.js deleted file mode 100644 index 86c2efe3a70bd..0000000000000 --- a/src/legacy/core_plugins/console/public/src/input.js +++ /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. - */ - -require('brace'); -require('brace/ext/searchbox'); -import Autocomplete from './autocomplete'; -import mappings from './mappings'; -const SenseEditor = require('./sense_editor/editor'); -const settings = require('./settings'); -const utils = require('./utils'); -const es = require('./es'); -const history = require('./history'); -import { uiModules } from 'ui/modules'; - -let input; -export function initializeInput($el, $actionsEl, $copyAsCurlEl, output, openDocumentation = () => {}) { - input = new SenseEditor($el); - - // this may not exist if running from tests - if (uiModules) { - const appSense = uiModules.get('app/sense'); - if (appSense && appSense.setupResizeCheckerForRootEditors) { - appSense.setupResizeCheckerForRootEditors($el, input, output); - } - } - - input.autocomplete = new Autocomplete(input); - - input.$actions = $actionsEl; - - input.commands.addCommand({ - name: 'auto indent request', - bindKey: { win: 'Ctrl-I', mac: 'Command-I' }, - exec: function () { - input.autoIndent(); - } - }); - input.commands.addCommand({ - name: 'move to previous request start or end', - bindKey: { win: 'Ctrl-Up', mac: 'Command-Up' }, - exec: function () { - input.moveToPreviousRequestEdge(); - } - }); - input.commands.addCommand({ - name: 'move to next request start or end', - bindKey: { win: 'Ctrl-Down', mac: 'Command-Down' }, - exec: function () { - input.moveToNextRequestEdge(); - } - }); - - /** - * Setup the "send" shortcut - */ - - let CURRENT_REQ_ID = 0; - - function sendCurrentRequestToES(addedToHistoryCb) { - - const reqId = ++CURRENT_REQ_ID; - - input.getRequestsInRange(function (requests) { - if (reqId !== CURRENT_REQ_ID) { - return; - } - output.update(''); - - if (requests.length === 0) { - return; - } - - const isMultiRequest = requests.length > 1; - const finishChain = function () { /* noop */ }; - - let isFirstRequest = true; - - const sendNextRequest = function () { - if (reqId !== CURRENT_REQ_ID) { - return; - } - if (requests.length === 0) { - finishChain(); - return; - } - const req = requests.shift(); - const esPath = req.url; - const esMethod = req.method; - let esData = utils.collapseLiteralStrings(req.data.join('\n')); - if (esData) { - esData += '\n'; - } //append a new line for bulk requests. - - es.send(esMethod, esPath, esData).always(function (dataOrjqXHR, textStatus, jqXhrORerrorThrown) { - if (reqId !== CURRENT_REQ_ID) { - return; - } - - const xhr = dataOrjqXHR.promise ? dataOrjqXHR : jqXhrORerrorThrown; - - function modeForContentType(contentType) { - if (contentType.indexOf('text/plain') >= 0) { - return 'ace/mode/text'; - } - else if (contentType.indexOf('application/yaml') >= 0) { - return 'ace/mode/yaml'; - } - return null; - } - - const isSuccess = typeof xhr.status === 'number' && - // Things like DELETE index where the index is not there are OK. - ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 404); - - if (isSuccess) { - if (xhr.status !== 404 && settings.getPolling()) { - // If the user has submitted a request against ES, something in the fields, indices, aliases, - // or templates may have changed, so we'll need to update this data. Assume that if - // the user disables polling they're trying to optimize performance or otherwise - // preserve resources, so they won't want this request sent either. - mappings.retrieveAutoCompleteInfo(); - } - - // we have someone on the other side. Add to history - history.addToHistory(esPath, esMethod, esData); - if (addedToHistoryCb) { - addedToHistoryCb(); - } - - let value = xhr.responseText; - const mode = modeForContentType(xhr.getAllResponseHeaders('Content-Type') || ''); - - // Apply triple quotes to output. - if (settings.getTripleQuotes() && (mode === null || mode === 'application/json')) { - // assume json - auto pretty - try { - value = utils.expandLiteralStrings(value); - } - catch (e) { - // nothing to do here - } - } - - const warnings = xhr.getResponseHeader('warning'); - if (warnings) { - const deprecationMessages = utils.extractDeprecationMessages(warnings); - value = deprecationMessages.join('\n') + '\n' + value; - } - - if (isMultiRequest) { - value = '# ' + req.method + ' ' + req.url + '\n' + value; - } - if (isFirstRequest) { - output.update(value, mode); - } - else { - output.append('\n' + value); - } - isFirstRequest = false; - // single request terminate via sendNextRequest as well - sendNextRequest(); - } else { - let value; - let mode; - if (xhr.responseText) { - value = xhr.responseText; // ES error should be shown - mode = modeForContentType(xhr.getAllResponseHeaders('Content-Type') || ''); - if (value[0] === '{') { - try { - value = JSON.stringify(JSON.parse(value), null, 2); - } - catch (e) { - // nothing to do here - } - } - } else { - value = 'Request failed to get to the server (status code: ' + xhr.status + ')'; - mode = 'ace/mode/text'; - } - if (isMultiRequest) { - value = '# ' + req.method + ' ' + req.url + '\n' + value; - } - if (isFirstRequest) { - output.update(value, mode); - } - else { - output.append('\n' + value); - } - finishChain(); - } - }); - }; - - sendNextRequest(); - }); - } - - - input.commands.addCommand({ - name: 'send to elasticsearch', - bindKey: { win: 'Ctrl-Enter', mac: 'Command-Enter' }, - exec: () => sendCurrentRequestToES() - }); - input.commands.addCommand({ - name: 'open documentation', - bindKey: { win: 'Ctrl-/', mac: 'Command-/' }, - exec: () => { - openDocumentation(); - } - }); - - /** - * Init the editor - */ - if (settings) { - settings.applyCurrentSettings(input); - } - input.focus(); - input.highlightCurrentRequestsAndUpdateActionBar(); - - input.sendCurrentRequestToES = sendCurrentRequestToES; - require('./input_resize')(input, output); - - return input; -} - -export default function getInput() { - return input; -} diff --git a/src/legacy/core_plugins/console/public/src/input_resize.js b/src/legacy/core_plugins/console/public/src/input_resize.js deleted file mode 100644 index 1afc952f699f4..0000000000000 --- a/src/legacy/core_plugins/console/public/src/input_resize.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. - */ - -const $ = require('jquery'); -const storage = require('./storage'); - -export default function (input, output) { - - const $left = input.$el.parent(); - - function readStoredEditorWidth() { - return storage.get('editorWidth'); - } - - function storeEditorWidth(editorWidth) { - storage.set('editorWidth', editorWidth); - } - - function setEditorWidth(editorWidth) { - storeEditorWidth(editorWidth); - $left.width(editorWidth); - } - - const $resizer = $('#ConAppResizer'); - $resizer - .on('mousedown', function (event) { - $resizer.addClass('active'); - const startWidth = $left.width(); - const startX = event.pageX; - input.resize.topRow = input.renderer.layerConfig.firstRow; - output.resize.topRow = output.renderer.layerConfig.firstRow; - - function onMove(event) { - setEditorWidth(startWidth + event.pageX - startX); - } - - $(document.body) - .on('mousemove', onMove) - .one('mouseup', function () { - $resizer.removeClass('active'); - $(this).off('mousemove', onMove); - input.resize(); - output.resize(); - }); - }); - - const initialEditorWidth = readStoredEditorWidth(); - if (initialEditorWidth != null) { - setEditorWidth(initialEditorWidth); - } - -} diff --git a/src/legacy/core_plugins/console/public/src/output.js b/src/legacy/core_plugins/console/public/src/output.js deleted file mode 100644 index 1c2781e13333e..0000000000000 --- a/src/legacy/core_plugins/console/public/src/output.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. - */ - -import _ from 'lodash'; -const ace = require('brace'); -const settings = require('./settings'); -const OutputMode = require('./sense_editor/mode/output'); -const smartResize = require('./smart_resize'); - -let output; -export function initializeOutput($el) { - output = ace.acequire('ace/ace').edit($el[0]); - - const outputMode = new OutputMode.Mode(); - - output.$blockScrolling = Infinity; - output.resize = smartResize(output); - output.update = function (val, mode, cb) { - if (typeof mode === 'function') { - cb = mode; - mode = void 0; - } - - const session = output.getSession(); - - session.setMode(val ? (mode || outputMode) : 'ace/mode/text'); - session.setValue(val); - if (typeof cb === 'function') { - setTimeout(cb); - } - }; - - output.append = function (val, foldPrevious, cb) { - if (typeof foldPrevious === 'function') { - cb = foldPrevious; - foldPrevious = true; - } - if (_.isUndefined(foldPrevious)) { - foldPrevious = true; - } - const session = output.getSession(); - const lastLine = session.getLength(); - if (foldPrevious) { - output.moveCursorTo(Math.max(0, lastLine - 1), 0); - } - session.insert({ row: lastLine, column: 0 }, '\n' + val); - output.moveCursorTo(lastLine + 1, 0); - if (typeof cb === 'function') { - setTimeout(cb); - } - }; - - output.$el = $el; - - (function (session) { - session.setMode('ace/mode/text'); - session.setFoldStyle('markbeginend'); - session.setTabSize(2); - session.setUseWrapMode(true); - }(output.getSession())); - - output.setShowPrintMargin(false); - output.setReadOnly(true); - - if (settings) { - settings.applyCurrentSettings(output); - } - - return output; -} - -export default function getOutput() { - return output; -} diff --git a/src/legacy/core_plugins/console/public/src/sense_editor/mode/output.js b/src/legacy/core_plugins/console/public/src/sense_editor/mode/output.js deleted file mode 100644 index e9964fa759726..0000000000000 --- a/src/legacy/core_plugins/console/public/src/sense_editor/mode/output.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. - */ - -const ace = require('brace'); -require('./output_highlight_rules'); - - -const oop = ace.acequire('ace/lib/oop'); -const JSONMode = ace.acequire('ace/mode/json').Mode; -const HighlightRules = require('./output_highlight_rules').OutputJsonHighlightRules; -const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; -const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour; -const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode; -ace.acequire('ace/worker/worker_client'); -const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer; - -export function Mode() { - this.$tokenizer = new AceTokenizer(new HighlightRules().getRules()); - this.$outdent = new MatchingBraceOutdent(); - this.$behaviour = new CstyleBehaviour(); - this.foldingRules = new CStyleFoldMode(); -} -oop.inherits(Mode, JSONMode); - -(function () { - this.createWorker = function () { - return null; - }; - - this.$id = 'sense/mode/input'; -}).call(Mode.prototype); diff --git a/src/legacy/core_plugins/console/public/src/sense_editor_resize.js b/src/legacy/core_plugins/console/public/src/sense_editor_resize.js deleted file mode 100644 index 6b950a394db1b..0000000000000 --- a/src/legacy/core_plugins/console/public/src/sense_editor_resize.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 { ResizeChecker } from 'ui/resize_checker'; - -export function applyResizeCheckerToEditors($scope, $el, ...editors) { - const checker = new ResizeChecker($el); - checker.on('resize', () => editors.forEach(e => e.resize())); - $scope.$on('$destroy', () => checker.destroy()); -} diff --git a/src/legacy/core_plugins/console/public/src/settings.js b/src/legacy/core_plugins/console/public/src/settings.js deleted file mode 100644 index 23e89d00563a3..0000000000000 --- a/src/legacy/core_plugins/console/public/src/settings.js +++ /dev/null @@ -1,102 +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 storage = require('./storage'); - -import getInput from './input'; -import getOutput from './output'; - -function getFontSize() { - return storage.get('font_size', 14); -} - -function setFontSize(size) { - storage.set('font_size', size); - applyCurrentSettings(); - return true; -} - -function getWrapMode() { - return storage.get('wrap_mode', true); -} - -function setWrapMode(mode) { - storage.set('wrap_mode', mode); - applyCurrentSettings(); - return true; -} - -function setTripleQuotes(tripleQuotes) { - storage.set('triple_quotes', tripleQuotes); - return true; -} - -export function getTripleQuotes() { - return storage.get('triple_quotes', true); -} - -export function getAutocomplete() { - return storage.get('autocomplete_settings', { fields: true, indices: true, templates: true }); -} - -function setAutocomplete(settings) { - storage.set('autocomplete_settings', settings); - return true; -} - -export function getPolling() { - return storage.get('console_polling', true); -} - -function setPolling(polling) { - storage.set('console_polling', polling); - applyCurrentSettings(); - return true; -} - -export function applyCurrentSettings(editor) { - if (typeof editor === 'undefined') { - applyCurrentSettings(getInput()); - applyCurrentSettings(getOutput()); - } - if (editor) { - editor.getSession().setUseWrapMode(getWrapMode()); - editor.$el.css('font-size', getFontSize() + 'px'); - } -} - -export function getCurrentSettings() { - return { - autocomplete: getAutocomplete(), - wrapMode: getWrapMode(), - tripleQuotes: getTripleQuotes(), - fontSize: parseFloat(getFontSize()), - polling: Boolean(getPolling()), - }; -} - -export function updateSettings({ fontSize, wrapMode, tripleQuotes, autocomplete, polling }) { - setFontSize(fontSize); - setWrapMode(wrapMode); - setTripleQuotes(tripleQuotes); - setAutocomplete(autocomplete); - setPolling(polling); - getInput().focus(); - return getCurrentSettings(); -} diff --git a/src/legacy/core_plugins/console/public/src/storage.js b/src/legacy/core_plugins/console/public/src/storage.js deleted file mode 100644 index fc8113287e971..0000000000000 --- a/src/legacy/core_plugins/console/public/src/storage.js +++ /dev/null @@ -1,79 +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 { transform, keys, startsWith } = require('lodash'); - -class Storage { - constructor(engine, prefix) { - this.engine = engine; - this.prefix = prefix; - } - - encode(val) { - return JSON.stringify(val); - } - - decode(val) { - if (typeof val === 'string') { - return JSON.parse(val); - } - } - - encodeKey(key) { - return `${this.prefix}${key}`; - } - - decodeKey(key) { - if (startsWith(key, this.prefix)) { - return `${key.slice(this.prefix.length)}`; - } - } - - set(key, val) { - this.engine.setItem(this.encodeKey(key), this.encode(val)); - return val; - } - - has(key) { - return this.engine.getItem(this.encodeKey(key)) != null; - } - - get(key, _default) { - if (this.has(key)) { - return this.decode(this.engine.getItem(this.encodeKey(key))); - } else { - return _default; - } - } - - delete(key) { - return this.engine.removeItem(this.encodeKey(key)); - } - - keys() { - return transform(keys(this.engine), (ours, key) => { - const ourKey = this.decodeKey(key); - if (ourKey != null) ours.push(ourKey); - }); - } -} - -const instance = new Storage(window.localStorage, 'sense:'); - -export default instance; diff --git a/src/legacy/core_plugins/console/public/src/utils.js b/src/legacy/core_plugins/console/public/src/utils.js deleted file mode 100644 index 1f2c3b9267b74..0000000000000 --- a/src/legacy/core_plugins/console/public/src/utils.js +++ /dev/null @@ -1,120 +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 _ from 'lodash'; - -const utils = {}; - -utils.textFromRequest = function (request) { - let data = request.data; - if (typeof data !== 'string') { - data = data.join('\n'); - } - return request.method + ' ' + request.url + '\n' + data; -}; - -utils.jsonToString = function (data, indent) { - return JSON.stringify(data, null, indent ? 2 : 0); -}; - -utils.reformatData = function (data, indent) { - let changed = false; - const formattedData = []; - for (let i = 0; i < data.length; i++) { - const curDoc = data[i]; - try { - let newDoc = utils.jsonToString(JSON.parse(utils.collapseLiteralStrings(curDoc)), indent ? 2 : 0); - if (indent) { - newDoc = utils.expandLiteralStrings(newDoc); - } - changed = changed || newDoc !== curDoc; - formattedData.push(newDoc); - } - catch (e) { - console.log(e); - formattedData.push(curDoc); - } - } - - return { - changed: changed, - data: formattedData - }; -}; - -utils.collapseLiteralStrings = function (data) { - return data.replace(/"""(?:\s*\r?\n)?((?:.|\r?\n)*?)(?:\r?\n\s*)?"""/g, function (match, literal) { - return JSON.stringify(literal); - }); -}; - -utils.expandLiteralStrings = function (data) { - return data.replace(/("(?:\\"|[^"])*?")/g, function (match, string) { - // expand things with two slashes or more - if (string.split(/\\./).length > 2) { - string = JSON.parse(string).replace('^\s*\n', '').replace('\n\s*^', ''); - const append = string.includes('\n') ? '\n' : ''; // only go multi line if the string has multiline - return '"""' + append + string + append + '"""'; - } else { - return string; - } - }); -}; - -utils.extractDeprecationMessages = function (warnings) { - // pattern for valid warning header - const re = /\d{3} [0-9a-zA-Z!#$%&'*+-.^_`|~]+ \"((?:\t| |!|[\x23-\x5b]|[\x5d-\x7e]|[\x80-\xff]|\\\\|\\")*)\"(?: \"[^"]*\")?/; - // split on any comma that is followed by an even number of quotes - return _.map(utils.splitOnUnquotedCommaSpace(warnings), function (warning) { - const match = re.exec(warning); - // extract the actual warning if there was a match - return '#! Deprecation: ' + (match !== null ? utils.unescape(match[1]) : warning); - }); -}; - -utils.unescape = function (s) { - return s.replace(/\\\\/g, '\\').replace(/\\"/g, '"'); -}; - -utils.splitOnUnquotedCommaSpace = function (s) { - let quoted = false; - const arr = []; - let buffer = ''; - let i = 0; - while (i < s.length) { - let token = s.charAt(i++); - if (token === '\\' && i < s.length) { - token += s.charAt(i++); - } else if (token === ',' && i < s.length && s.charAt(i) === ' ') { - token += s.charAt(i++); - } - if (token === '"') { - quoted = !quoted; - } else if (!quoted && token === ', ') { - arr.push(buffer); - buffer = ''; - continue; - } - buffer += token; - } - arr.push(buffer); - return arr; -}; - -export default utils; diff --git a/src/legacy/core_plugins/console/public/tests/src/setup_mocks.js b/src/legacy/core_plugins/console/public/tests/src/setup_mocks.js deleted file mode 100644 index 0bcf75e29f5f3..0000000000000 --- a/src/legacy/core_plugins/console/public/tests/src/setup_mocks.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. - */ -/* eslint no-undef: 0 */ -jest.mock('../../src/sense_editor/mode/worker', () => { return { workerModule: { id: 'sense_editor/mode/worker', src: '' } }; }); -window.Worker = function () { this.postMessage = () => {}; this.terminate = () => {}; }; -window.URL = { - createObjectURL: () => { return ''; } -}; -jest.mock('../../src/storage'); - -document.queryCommandSupported = () => true; - -import jQuery from 'jquery'; -jest.spyOn(jQuery, 'ajax').mockImplementation(() => new Promise(() => { - // never resolve -})); diff --git a/src/legacy/core_plugins/console/public/tests/src/utils_string_expanding.txt b/src/legacy/core_plugins/console/public/tests/src/utils_string_expanding.txt deleted file mode 100644 index 762e0ad164634..0000000000000 --- a/src/legacy/core_plugins/console/public/tests/src/utils_string_expanding.txt +++ /dev/null @@ -1,21 +0,0 @@ -========== -Scripts in requests -------------------------------------- -{ - "f": { "script" : { "source": "test\ntest\\2" } }, - "g": { "script" : "second + \"\\\";" }, - "f": "short with \\", - "h": 1, - "script": "a + 2" -} -------------------------------------- -{ - "f": { "script" : { "source": """ -test -test\2 -""" } }, - "g": { "script" : """second + "\";""" }, - "f": "short with \\", - "h": 1, - "script": "a + 2" -} diff --git a/src/legacy/core_plugins/console/api_server/api.js b/src/legacy/core_plugins/console/server/api_server/api.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/api.js rename to src/legacy/core_plugins/console/server/api_server/api.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0.js b/src/legacy/core_plugins/console/server/api_server/es_6_0.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/aggregations.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/aggregations.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/aggregations.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/aggregations.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/aliases.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/aliases.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/aliases.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/aliases.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/document.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/document.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/document.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/document.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/filter.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/filter.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/filter.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/filter.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/globals.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/globals.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/globals.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/globals.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/ingest.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/ingest.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/ingest.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/ingest.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/mappings.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/mappings.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/mappings.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/mappings.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/query/dsl.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/query/dsl.js similarity index 98% rename from src/legacy/core_plugins/console/api_server/es_6_0/query/dsl.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/query/dsl.js index 4a49ed0375f7c..fd86446532ed7 100644 --- a/src/legacy/core_plugins/console/api_server/es_6_0/query/dsl.js +++ b/src/legacy/core_plugins/console/server/api_server/es_6_0/query/dsl.js @@ -337,6 +337,16 @@ export function queryDsl(api) { }, ], }, + distance_feature: { + __template: { + field: '', + origin: '', + pivot: '', + }, + field: '{field}', + origin: '', + pivot: '', + }, exists: { field: '', }, diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/query/index.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/query/index.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/query/index.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/query/index.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/query/templates.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/query/templates.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/query/templates.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/query/templates.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/reindex.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/reindex.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/reindex.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/reindex.js diff --git a/src/legacy/core_plugins/console/api_server/es_6_0/search.js b/src/legacy/core_plugins/console/server/api_server/es_6_0/search.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/es_6_0/search.js rename to src/legacy/core_plugins/console/server/api_server/es_6_0/search.js diff --git a/src/legacy/core_plugins/console/api_server/server.js b/src/legacy/core_plugins/console/server/api_server/server.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/server.js rename to src/legacy/core_plugins/console/server/api_server/server.js diff --git a/src/legacy/core_plugins/console/api_server/server.test.js b/src/legacy/core_plugins/console/server/api_server/server.test.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/server.test.js rename to src/legacy/core_plugins/console/server/api_server/server.test.js diff --git a/src/legacy/core_plugins/console/api_server/spec/.eslintrc b/src/legacy/core_plugins/console/server/api_server/spec/.eslintrc similarity index 92% rename from src/legacy/core_plugins/console/api_server/spec/.eslintrc rename to src/legacy/core_plugins/console/server/api_server/spec/.eslintrc index b302d39e1dfd1..46052f0e19a0d 100644 --- a/src/legacy/core_plugins/console/api_server/spec/.eslintrc +++ b/src/legacy/core_plugins/console/server/api_server/spec/.eslintrc @@ -1,7 +1,7 @@ --- root: true -extends: '../../../../../../.eslintrc.js' +extends: '../../../../../../../.eslintrc.js' rules: block-scoped-var: off diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/_common.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/_common.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/_common.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/_common.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/bulk.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/bulk.json similarity index 82% rename from src/legacy/core_plugins/console/api_server/spec/generated/bulk.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/bulk.json index 4cece8610ed55..2d3bd260372ba 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/bulk.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/bulk.json @@ -24,6 +24,6 @@ "{indices}/_bulk", "{indices}/{type}/_bulk" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-bulk.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-bulk.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.aliases.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.aliases.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.aliases.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.aliases.json index 3e749c4de7852..704cd39816040 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.aliases.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.aliases.json @@ -16,6 +16,6 @@ "_cat/aliases", "_cat/aliases/{name}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-alias.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-alias.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.allocation.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.allocation.json similarity index 82% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.allocation.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.allocation.json index 9900363b80ee7..4d77575f959ba 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.allocation.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.allocation.json @@ -29,6 +29,6 @@ "_cat/allocation", "_cat/allocation/{nodes}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-allocation.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-allocation.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.count.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.count.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.count.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.count.json index 392bee6f90599..56377699e004e 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.count.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.count.json @@ -16,6 +16,6 @@ "_cat/count", "_cat/count/{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-count.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-count.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.fielddata.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.fielddata.json similarity index 83% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.fielddata.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.fielddata.json index 970ed974b41a2..8e7d73333ab32 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.fielddata.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.fielddata.json @@ -30,6 +30,6 @@ "_cat/fielddata", "_cat/fielddata/{fields}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-fielddata.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-fielddata.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.health.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.health.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.health.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.health.json index 0cc04d2bd7565..9bf7b17b7a2a9 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.health.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.health.json @@ -16,6 +16,6 @@ "patterns": [ "_cat/health" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-health.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-health.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.help.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.help.json new file mode 100644 index 0000000000000..f46c1721fdf36 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.help.json @@ -0,0 +1,15 @@ +{ + "cat.help": { + "url_params": { + "help": "__flag__", + "s": [] + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.indices.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.indices.json similarity index 84% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.indices.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.indices.json index ab188aa19331d..a67ed9aa7282c 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.indices.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.indices.json @@ -29,6 +29,6 @@ "_cat/indices", "_cat/indices/{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-indices.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-indices.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.master.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.master.json new file mode 100644 index 0000000000000..6ae3e54d5c853 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.master.json @@ -0,0 +1,20 @@ +{ + "cat.master": { + "url_params": { + "format": "", + "local": "__flag__", + "master_timeout": "", + "h": [], + "help": "__flag__", + "s": [], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/master" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-master.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.nodeattrs.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.nodeattrs.json new file mode 100644 index 0000000000000..191985c7bc6d5 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.nodeattrs.json @@ -0,0 +1,20 @@ +{ + "cat.nodeattrs": { + "url_params": { + "format": "", + "local": "__flag__", + "master_timeout": "", + "h": [], + "help": "__flag__", + "s": [], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/nodeattrs" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-nodeattrs.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.nodes.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.nodes.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.nodes.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.nodes.json index fd15246811f8b..650fe122ba548 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.nodes.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.nodes.json @@ -16,6 +16,6 @@ "patterns": [ "_cat/nodes" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-nodes.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-nodes.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.pending_tasks.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.pending_tasks.json new file mode 100644 index 0000000000000..e719875745bdc --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.pending_tasks.json @@ -0,0 +1,20 @@ +{ + "cat.pending_tasks": { + "url_params": { + "format": "", + "local": "__flag__", + "master_timeout": "", + "h": [], + "help": "__flag__", + "s": [], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/pending_tasks" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-pending-tasks.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.plugins.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.plugins.json new file mode 100644 index 0000000000000..958992be81216 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.plugins.json @@ -0,0 +1,20 @@ +{ + "cat.plugins": { + "url_params": { + "format": "", + "local": "__flag__", + "master_timeout": "", + "h": [], + "help": "__flag__", + "s": [], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/plugins" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-plugins.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.recovery.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.recovery.json similarity index 81% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.recovery.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.recovery.json index ee8bf0a791039..49e2f2a97b852 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.recovery.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.recovery.json @@ -28,6 +28,6 @@ "_cat/recovery", "_cat/recovery/{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-recovery.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-recovery.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.repositories.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.repositories.json new file mode 100644 index 0000000000000..6ce2f7c10c8ca --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.repositories.json @@ -0,0 +1,20 @@ +{ + "cat.repositories": { + "url_params": { + "format": "", + "local": "__flag__", + "master_timeout": "", + "h": [], + "help": "__flag__", + "s": [], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/repositories" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-repositories.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.segments.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.segments.json similarity index 80% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.segments.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.segments.json index ffd771e5e4f7f..39bd21f4272d9 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.segments.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.segments.json @@ -27,6 +27,6 @@ "_cat/segments", "_cat/segments/{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-segments.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-segments.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.shards.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.shards.json similarity index 82% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.shards.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.shards.json index e0ce5cb1567c1..767131c0bd009 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.shards.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.shards.json @@ -29,6 +29,6 @@ "_cat/shards", "_cat/shards/{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-shards.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-shards.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.snapshots.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.snapshots.json similarity index 76% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.snapshots.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.snapshots.json index dbb6023fcc83b..ebfa59c43333b 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.snapshots.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.snapshots.json @@ -16,6 +16,6 @@ "_cat/snapshots", "_cat/snapshots/{repository}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-snapshots.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-snapshots.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.tasks.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.tasks.json similarity index 77% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.tasks.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.tasks.json index ac5e907bd30fe..542a66491f9c4 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.tasks.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.tasks.json @@ -17,6 +17,6 @@ "patterns": [ "_cat/tasks" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.templates.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.templates.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.templates.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.templates.json index f8c35873aeed1..2ff756838facf 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.templates.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.templates.json @@ -16,6 +16,6 @@ "_cat/templates", "_cat/templates/{name}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-templates.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-templates.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cat.thread_pool.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.thread_pool.json similarity index 80% rename from src/legacy/core_plugins/console/api_server/spec/generated/cat.thread_pool.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cat.thread_pool.json index 508f1f2ff5f24..5017a0390a2e4 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cat.thread_pool.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.thread_pool.json @@ -24,6 +24,6 @@ "_cat/thread_pool", "_cat/thread_pool/{thread_pool_patterns}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-thread-pool.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cat-thread-pool.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/clear_scroll.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/clear_scroll.json new file mode 100644 index 0000000000000..9d7d29654f851 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/clear_scroll.json @@ -0,0 +1,12 @@ +{ + "clear_scroll": { + "methods": [ + "DELETE" + ], + "patterns": [ + "_search/scroll", + "_search/scroll/{scroll_id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-body.html#request-body-search-scroll" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.allocation_explain.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.allocation_explain.json new file mode 100644 index 0000000000000..c62c58bac45b3 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.allocation_explain.json @@ -0,0 +1,16 @@ +{ + "cluster.allocation_explain": { + "url_params": { + "include_yes_decisions": "__flag__", + "include_disk_info": "__flag__" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_cluster/allocation/explain" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-allocation-explain.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.get_settings.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.get_settings.json new file mode 100644 index 0000000000000..249f582c33682 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.get_settings.json @@ -0,0 +1,17 @@ +{ + "cluster.get_settings": { + "url_params": { + "flat_settings": "__flag__", + "master_timeout": "", + "timeout": "", + "include_defaults": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cluster/settings" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.health.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.health.json similarity index 88% rename from src/legacy/core_plugins/console/api_server/spec/generated/cluster.health.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.health.json index 138921bf022d3..64ede603c0e0d 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.health.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.health.json @@ -40,6 +40,6 @@ "_cluster/health", "_cluster/health/{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-health.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-health.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.pending_tasks.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.pending_tasks.json new file mode 100644 index 0000000000000..f6c6439483dca --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.pending_tasks.json @@ -0,0 +1,15 @@ +{ + "cluster.pending_tasks": { + "url_params": { + "local": "__flag__", + "master_timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cluster/pending_tasks" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-pending.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.put_settings.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.put_settings.json new file mode 100644 index 0000000000000..30598ad7dafe0 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.put_settings.json @@ -0,0 +1,16 @@ +{ + "cluster.put_settings": { + "url_params": { + "flat_settings": "__flag__", + "master_timeout": "", + "timeout": "" + }, + "methods": [ + "PUT" + ], + "patterns": [ + "_cluster/settings" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.remote_info.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.remote_info.json new file mode 100644 index 0000000000000..559f5ff1da526 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.remote_info.json @@ -0,0 +1,11 @@ +{ + "cluster.remote_info": { + "methods": [ + "GET" + ], + "patterns": [ + "_remote/info" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-remote-info.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.reroute.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.reroute.json new file mode 100644 index 0000000000000..777df671f4d86 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.reroute.json @@ -0,0 +1,19 @@ +{ + "cluster.reroute": { + "url_params": { + "dry_run": "__flag__", + "explain": "__flag__", + "retry_failed": "__flag__", + "metric": [], + "master_timeout": "", + "timeout": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_cluster/reroute" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-reroute.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.state.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.state.json similarity index 84% rename from src/legacy/core_plugins/console/api_server/spec/generated/cluster.state.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.state.json index bb8affc7ba3f3..ba9c8d427e7bd 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/cluster.state.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.state.json @@ -24,7 +24,6 @@ "_cluster/state/{metrics}/{indices}" ], "url_components": { - "indices": null, "metrics": [ "_all", "blocks", @@ -34,8 +33,9 @@ "routing_nodes", "routing_table", "version" - ] + ], + "indices": null }, - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-state.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-state.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.stats.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.stats.json new file mode 100644 index 0000000000000..be7187ec85e42 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cluster.stats.json @@ -0,0 +1,16 @@ +{ + "cluster.stats": { + "url_params": { + "flat_settings": "__flag__", + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cluster/stats", + "_cluster/stats/nodes/{nodes}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-stats.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/count.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/count.json similarity index 86% rename from src/legacy/core_plugins/console/api_server/spec/generated/count.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/count.json index b96874d8781c3..bd69fd0c77ec8 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/count.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/count.json @@ -32,6 +32,6 @@ "_count", "{indices}/_count" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-count.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-count.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/create.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/create.json new file mode 100644 index 0000000000000..7433628a4744f --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/create.json @@ -0,0 +1,31 @@ +{ + "create": { + "url_params": { + "wait_for_active_shards": "", + "refresh": [ + "true", + "false", + "wait_for" + ], + "routing": "", + "timeout": "", + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ], + "pipeline": "" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "{indices}/_create/{id}", + "{indices}/{type}/{id}/_create" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete.json new file mode 100644 index 0000000000000..aba84d0a10fc2 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete.json @@ -0,0 +1,31 @@ +{ + "delete": { + "url_params": { + "wait_for_active_shards": "", + "refresh": [ + "true", + "false", + "wait_for" + ], + "routing": "", + "timeout": "", + "if_seq_no": "", + "if_primary_term": "", + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ] + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "{indices}/_doc/{id}", + "{indices}/{type}/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-delete.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/delete_by_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json similarity index 98% rename from src/legacy/core_plugins/console/api_server/spec/generated/delete_by_query.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json index 468fb974bac70..3867efd814238 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/delete_by_query.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json @@ -31,7 +31,6 @@ "dfs_query_then_fetch" ], "search_timeout": "", - "size": "", "max_docs": "all documents", "sort": [], "_source": [], diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/delete_by_query_rethrottle.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query_rethrottle.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/delete_by_query_rethrottle.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query_rethrottle.json diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_script.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_script.json new file mode 100644 index 0000000000000..2db3e09cb9ec6 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_script.json @@ -0,0 +1,15 @@ +{ + "delete_script": { + "url_params": { + "timeout": "", + "master_timeout": "" + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "_scripts/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/exists.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists.json new file mode 100644 index 0000000000000..4b7b18b9fe1b3 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists.json @@ -0,0 +1,29 @@ +{ + "exists": { + "url_params": { + "stored_fields": [], + "preference": "random", + "realtime": "__flag__", + "refresh": "__flag__", + "routing": "", + "_source": [], + "_source_excludes": [], + "_source_includes": [], + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ] + }, + "methods": [ + "HEAD" + ], + "patterns": [ + "{indices}/_doc/{id}", + "{indices}/{type}/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/exists_source.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists_source.json new file mode 100644 index 0000000000000..e96273ffbc083 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists_source.json @@ -0,0 +1,28 @@ +{ + "exists_source": { + "url_params": { + "preference": "random", + "realtime": "__flag__", + "refresh": "__flag__", + "routing": "", + "_source": [], + "_source_excludes": [], + "_source_includes": [], + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ] + }, + "methods": [ + "HEAD" + ], + "patterns": [ + "{indices}/_source/{id}", + "{indices}/{type}/{id}/_source" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/explain.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/explain.json new file mode 100644 index 0000000000000..be01e462878db --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/explain.json @@ -0,0 +1,30 @@ +{ + "explain": { + "url_params": { + "analyze_wildcard": "__flag__", + "analyzer": "", + "default_operator": [ + "AND", + "OR" + ], + "df": "_all", + "stored_fields": [], + "lenient": "__flag__", + "preference": "random", + "q": "", + "routing": "", + "_source": [], + "_source_excludes": [], + "_source_includes": [] + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "{indices}/_explain/{id}", + "{indices}/{type}/{id}/_explain" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-explain.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/field_caps.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/field_caps.json similarity index 79% rename from src/legacy/core_plugins/console/api_server/spec/generated/field_caps.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/field_caps.json index 08b4139507fed..5e632018bef25 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/field_caps.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/field_caps.json @@ -20,6 +20,6 @@ "_field_caps", "{indices}/_field_caps" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-field-caps.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-field-caps.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/get.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/get.json new file mode 100644 index 0000000000000..a0b70545baff9 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/get.json @@ -0,0 +1,29 @@ +{ + "get": { + "url_params": { + "stored_fields": [], + "preference": "random", + "realtime": "__flag__", + "refresh": "__flag__", + "routing": "", + "_source": [], + "_source_excludes": [], + "_source_includes": [], + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ] + }, + "methods": [ + "GET" + ], + "patterns": [ + "{indices}/_doc/{id}", + "{indices}/{type}/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script.json new file mode 100644 index 0000000000000..77fd5e8cd46ea --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script.json @@ -0,0 +1,14 @@ +{ + "get_script": { + "url_params": { + "master_timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_scripts/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/get_source.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_source.json new file mode 100644 index 0000000000000..420e03a1bdcf1 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_source.json @@ -0,0 +1,28 @@ +{ + "get_source": { + "url_params": { + "preference": "random", + "realtime": "__flag__", + "refresh": "__flag__", + "routing": "", + "_source": [], + "_source_excludes": [], + "_source_includes": [], + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ] + }, + "methods": [ + "GET" + ], + "patterns": [ + "{indices}/_source/{id}", + "{indices}/{type}/{id}/_source" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/index.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/index.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/index.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/index.json index 4da4f1994306f..ed3b97125339a 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/index.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/index.json @@ -30,8 +30,10 @@ ], "patterns": [ "{indices}/_doc/{id}", - "{indices}/_doc" + "{indices}/_doc", + "{indices}/{type}", + "{indices}/{type}/{id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.analyze.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.analyze.json new file mode 100644 index 0000000000000..6b7c7187ab145 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.analyze.json @@ -0,0 +1,16 @@ +{ + "indices.analyze": { + "url_params": { + "index": "" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_analyze", + "{indices}/_analyze" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-analyze.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.clear_cache.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.clear_cache.json similarity index 81% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.clear_cache.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.clear_cache.json index 94d6dfaf6eaa4..f5cf05c9a3f7f 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.clear_cache.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.clear_cache.json @@ -22,6 +22,6 @@ "_cache/clear", "{indices}/_cache/clear" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-clearcache.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-clearcache.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.clone.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.clone.json new file mode 100644 index 0000000000000..8d5e76c0abcc9 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.clone.json @@ -0,0 +1,17 @@ +{ + "indices.clone": { + "url_params": { + "timeout": "", + "master_timeout": "", + "wait_for_active_shards": "" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "{indices}/_clone/{target}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-clone-index.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.close.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.close.json similarity index 78% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.close.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.close.json index 736c60c486432..676f20632e63b 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.close.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.close.json @@ -19,6 +19,6 @@ "patterns": [ "{indices}/_close" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.create.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.create.json new file mode 100644 index 0000000000000..1970f88b30958 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.create.json @@ -0,0 +1,17 @@ +{ + "indices.create": { + "url_params": { + "include_type_name": "__flag__", + "wait_for_active_shards": "", + "timeout": "", + "master_timeout": "" + }, + "methods": [ + "PUT" + ], + "patterns": [ + "{indices}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-create-index.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete.json similarity index 76% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.delete.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete.json index 234c8c1e28de8..b006d5ea7a3cb 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.delete.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete.json @@ -18,6 +18,6 @@ "patterns": [ "{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-delete-index.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-delete-index.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete_alias.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete_alias.json new file mode 100644 index 0000000000000..d19ec28993937 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete_alias.json @@ -0,0 +1,16 @@ +{ + "indices.delete_alias": { + "url_params": { + "timeout": "", + "master_timeout": "" + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "{indices}/_alias/{name}", + "{indices}/_aliases/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete_template.json new file mode 100644 index 0000000000000..7e5772115d113 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.delete_template.json @@ -0,0 +1,15 @@ +{ + "indices.delete_template": { + "url_params": { + "timeout": "", + "master_timeout": "" + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "_template/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists.json similarity index 79% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.exists.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists.json index 6a51a8784fa9f..33c845210ea87 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists.json @@ -19,6 +19,6 @@ "patterns": [ "{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-exists.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-exists.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_alias.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_alias.json similarity index 78% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_alias.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_alias.json index e990998efef2e..d302bbe6b93de 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_alias.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_alias.json @@ -18,6 +18,6 @@ "_alias/{name}", "{indices}/_alias/{name}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_template.json new file mode 100644 index 0000000000000..89972447e81af --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_template.json @@ -0,0 +1,16 @@ +{ + "indices.exists_template": { + "url_params": { + "flat_settings": "__flag__", + "master_timeout": "", + "local": "__flag__" + }, + "methods": [ + "HEAD" + ], + "patterns": [ + "_template/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_type.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_type.json similarity index 76% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_type.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_type.json index d20e08ab2cf53..70d35e6c453c9 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.exists_type.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.exists_type.json @@ -17,6 +17,6 @@ "patterns": [ "{indices}/_mapping/{type}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-types-exists.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-types-exists.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.flush.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.flush.json similarity index 79% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.flush.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.flush.json index 2e2361edb2112..0ad1a250229b2 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.flush.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.flush.json @@ -20,6 +20,6 @@ "_flush", "{indices}/_flush" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-flush.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-flush.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.flush_synced.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.flush_synced.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.flush_synced.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.flush_synced.json index 12e08963ebef5..3a2f5a00f8974 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.flush_synced.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.flush_synced.json @@ -18,6 +18,6 @@ "_flush/synced", "{indices}/_flush/synced" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-synced-flush.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-flush.html#synced-flush-api" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.forcemerge.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.forcemerge.json similarity index 80% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.forcemerge.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.forcemerge.json index 7b4e15a702afc..0e705e2e721ee 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.forcemerge.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.forcemerge.json @@ -20,6 +20,6 @@ "_forcemerge", "{indices}/_forcemerge" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-forcemerge.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-forcemerge.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get.json similarity index 81% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.get.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get.json index 01fce6c61ac7e..f515e73b250a7 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get.json @@ -21,6 +21,6 @@ "patterns": [ "{indices}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-index.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-index.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_alias.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_alias.json similarity index 79% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.get_alias.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_alias.json index 1b24c35f76d98..d687cab56630f 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_alias.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_alias.json @@ -20,6 +20,6 @@ "{indices}/_alias/{name}", "{indices}/_alias" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_field_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_field_mapping.json new file mode 100644 index 0000000000000..ae82696434ced --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_field_mapping.json @@ -0,0 +1,27 @@ +{ + "indices.get_field_mapping": { + "url_params": { + "include_type_name": "__flag__", + "include_defaults": "__flag__", + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ], + "local": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_mapping/field/{fields}", + "{indices}/_mapping/field/{fields}", + "_mapping/{type}/field/{fields}", + "{indices}/_mapping/{type}/field/{fields}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-field-mapping.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_mapping.json new file mode 100644 index 0000000000000..03f5de56ea351 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_mapping.json @@ -0,0 +1,27 @@ +{ + "indices.get_mapping": { + "url_params": { + "include_type_name": "__flag__", + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ], + "master_timeout": "", + "local": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_mapping", + "{indices}/_mapping", + "_mapping/{type}", + "{indices}/_mapping/{type}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-mapping.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_settings.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_settings.json similarity index 82% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.get_settings.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_settings.json index 25c8c215866e7..1c84258d0fce9 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_settings.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_settings.json @@ -23,6 +23,6 @@ "{indices}/_settings/{name}", "_settings/{name}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-settings.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-settings.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_template.json new file mode 100644 index 0000000000000..d5f52ec76b374 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_template.json @@ -0,0 +1,18 @@ +{ + "indices.get_template": { + "url_params": { + "include_type_name": "__flag__", + "flat_settings": "__flag__", + "master_timeout": "", + "local": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_template", + "_template/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_upgrade.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_upgrade.json similarity index 76% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.get_upgrade.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_upgrade.json index 7da594a5bf784..d781172c54d63 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.get_upgrade.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.get_upgrade.json @@ -17,6 +17,6 @@ "_upgrade", "{indices}/_upgrade" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-upgrade.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-upgrade.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.open.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.open.json similarity index 78% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.open.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.open.json index 2b721566101fd..b5c4c5501d05d 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.open.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.open.json @@ -19,6 +19,6 @@ "patterns": [ "{indices}/_open" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_alias.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_alias.json new file mode 100644 index 0000000000000..a6e9091296b3b --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_alias.json @@ -0,0 +1,17 @@ +{ + "indices.put_alias": { + "url_params": { + "timeout": "", + "master_timeout": "" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "{indices}/_alias/{name}", + "{indices}/_aliases/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_mapping.json new file mode 100644 index 0000000000000..3b833117be499 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_mapping.json @@ -0,0 +1,32 @@ +{ + "indices.put_mapping": { + "url_params": { + "include_type_name": "__flag__", + "timeout": "", + "master_timeout": "", + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ] + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "{indices}/_mapping", + "{indices}/{type}/_mapping", + "{indices}/_mapping/{type}", + "{indices}/{type}/_mappings", + "{indices}/_mappings/{type}", + "_mappings/{type}", + "{indices}/_mappings", + "_mapping/{type}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-put-mapping.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_settings.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_settings.json similarity index 80% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.put_settings.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_settings.json index de409796f84a6..fe7b938d2f3fc 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_settings.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_settings.json @@ -21,6 +21,6 @@ "_settings", "{indices}/_settings" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-update-settings.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-update-settings.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_template.json similarity index 75% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.put_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_template.json index abd410761c9e4..8b3480f24d8fb 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.put_template.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.put_template.json @@ -15,6 +15,6 @@ "patterns": [ "_template/{name}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.recovery.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.recovery.json new file mode 100644 index 0000000000000..fc3eadb23bbad --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.recovery.json @@ -0,0 +1,16 @@ +{ + "indices.recovery": { + "url_params": { + "detailed": "__flag__", + "active_only": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_recovery", + "{indices}/_recovery" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-recovery.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.refresh.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.refresh.json similarity index 76% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.refresh.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.refresh.json index a696d7b1f4180..54cd2a869902a 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.refresh.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.refresh.json @@ -18,6 +18,6 @@ "_refresh", "{indices}/_refresh" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-refresh.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-refresh.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.rollover.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.rollover.json new file mode 100644 index 0000000000000..7fa76a687eb77 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.rollover.json @@ -0,0 +1,19 @@ +{ + "indices.rollover": { + "url_params": { + "include_type_name": "__flag__", + "timeout": "", + "dry_run": "__flag__", + "master_timeout": "", + "wait_for_active_shards": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "{alias}/_rollover", + "{alias}/_rollover/{new_index}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-rollover-index.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.segments.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.segments.json similarity index 77% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.segments.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.segments.json index b3f87eab2251b..9e2eb6efce27e 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.segments.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.segments.json @@ -18,6 +18,6 @@ "_segments", "{indices}/_segments" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-segments.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-segments.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.shard_stores.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shard_stores.json similarity index 76% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.shard_stores.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shard_stores.json index 7822604d1b5f4..f8e026eb89984 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.shard_stores.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shard_stores.json @@ -18,6 +18,6 @@ "_shard_stores", "{indices}/_shard_stores" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shards-stores.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shards-stores.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json new file mode 100644 index 0000000000000..31acc86a2fa56 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json @@ -0,0 +1,17 @@ +{ + "indices.shrink": { + "url_params": { + "timeout": "", + "master_timeout": "", + "wait_for_active_shards": "" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "{indices}/_shrink/{target}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shrink-index.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json new file mode 100644 index 0000000000000..1bfbaa078b796 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json @@ -0,0 +1,17 @@ +{ + "indices.split": { + "url_params": { + "timeout": "", + "master_timeout": "", + "wait_for_active_shards": "" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "{indices}/_split/{target}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-split-index.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.stats.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.stats.json similarity index 88% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.stats.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.stats.json index 74031d303c213..c3fc0f8f7055f 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.stats.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.stats.json @@ -31,7 +31,6 @@ "{indices}/_stats/{metrics}" ], "url_components": { - "indices": null, "metrics": [ "_all", "completion", @@ -49,8 +48,9 @@ "store", "suggest", "warmer" - ] + ], + "indices": null }, - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-stats.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-stats.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.update_aliases.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.update_aliases.json new file mode 100644 index 0000000000000..834115fe2cb11 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.update_aliases.json @@ -0,0 +1,15 @@ +{ + "indices.update_aliases": { + "url_params": { + "timeout": "", + "master_timeout": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_aliases" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.upgrade.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.upgrade.json similarity index 79% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.upgrade.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.upgrade.json index 3382f069a00ec..68ee06dd1b0bd 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.upgrade.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.upgrade.json @@ -19,6 +19,6 @@ "_upgrade", "{indices}/_upgrade" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-upgrade.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-upgrade.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/indices.validate_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.validate_query.json similarity index 77% rename from src/legacy/core_plugins/console/api_server/spec/generated/indices.validate_query.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/indices.validate_query.json index c777a50175471..ceffec26beecc 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/indices.validate_query.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.validate_query.json @@ -28,8 +28,9 @@ ], "patterns": [ "_validate/query", - "{indices}/_validate/query" + "{indices}/_validate/query", + "{indices}/{type}/_validate/query" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-validate.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-validate.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/info.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/info.json new file mode 100644 index 0000000000000..87c5cf9965b3e --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/info.json @@ -0,0 +1,11 @@ +{ + "info": { + "methods": [ + "GET" + ], + "patterns": [ + "" + ], + "documentation": "https://www.elastic.co/guide/" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/ingest.delete_pipeline.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.delete_pipeline.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/ingest.delete_pipeline.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.delete_pipeline.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/ingest.get_pipeline.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.get_pipeline.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/ingest.get_pipeline.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.get_pipeline.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/ingest.processor_grok.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.processor_grok.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/ingest.processor_grok.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.processor_grok.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/ingest.put_pipeline.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.put_pipeline.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/ingest.put_pipeline.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.put_pipeline.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/ingest.simulate.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.simulate.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/ingest.simulate.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/ingest.simulate.json diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/mget.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/mget.json new file mode 100644 index 0000000000000..f84b46a379cf4 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/mget.json @@ -0,0 +1,24 @@ +{ + "mget": { + "url_params": { + "stored_fields": [], + "preference": "random", + "realtime": "__flag__", + "refresh": "__flag__", + "routing": "", + "_source": [], + "_source_excludes": [], + "_source_includes": [] + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_mget", + "{indices}/_mget", + "{indices}/{type}/_mget" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-get.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/msearch.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch.json similarity index 83% rename from src/legacy/core_plugins/console/api_server/spec/generated/msearch.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/msearch.json index 2fca64e53dda7..ecb71e9ba23c0 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/msearch.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch.json @@ -22,6 +22,6 @@ "_msearch", "{indices}/_msearch" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-multi-search.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-multi-search.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/msearch_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json similarity index 81% rename from src/legacy/core_plugins/console/api_server/spec/generated/msearch_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json index e0886ee35e8fa..0b0ca087b1819 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/msearch_template.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json @@ -20,6 +20,6 @@ "_msearch/template", "{indices}/_msearch/template" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/mtermvectors.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/mtermvectors.json similarity index 84% rename from src/legacy/core_plugins/console/api_server/spec/generated/mtermvectors.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/mtermvectors.json index 2ec55936e25f4..72a134eca4d2e 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/mtermvectors.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/mtermvectors.json @@ -27,6 +27,6 @@ "_mtermvectors", "{indices}/_mtermvectors" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-termvectors.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-termvectors.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.hot_threads.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.hot_threads.json new file mode 100644 index 0000000000000..b8aa5dd4ca711 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.hot_threads.json @@ -0,0 +1,30 @@ +{ + "nodes.hot_threads": { + "url_params": { + "interval": "", + "snapshots": "10", + "threads": "3", + "ignore_idle_threads": "__flag__", + "type": [ + "cpu", + "wait", + "block" + ], + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_nodes/hot_threads", + "_nodes/{nodes}/hot_threads", + "_cluster/nodes/hotthreads", + "_cluster/nodes/{nodes}/hotthreads", + "_nodes/hotthreads", + "_nodes/{nodes}/hotthreads", + "_cluster/nodes/hot_threads", + "_cluster/nodes/{nodes}/hot_threads" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-hot-threads.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.info.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.info.json similarity index 82% rename from src/legacy/core_plugins/console/api_server/spec/generated/nodes.info.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.info.json index a4938acb27538..6f35b9c6f6a62 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.info.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.info.json @@ -27,6 +27,6 @@ "transport" ] }, - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-info.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-info.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.reload_secure_settings.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.reload_secure_settings.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/nodes.reload_secure_settings.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.reload_secure_settings.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.stats.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.stats.json similarity index 89% rename from src/legacy/core_plugins/console/api_server/spec/generated/nodes.stats.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.stats.json index 0073f224e3abf..e194a6d42c031 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/nodes.stats.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.stats.json @@ -26,6 +26,7 @@ "_nodes/{nodes}/stats/{metrics}/{index_metric}" ], "url_components": { + "nodes": null, "metrics": [ "_all", "breaker", @@ -56,9 +57,8 @@ "store", "suggest", "warmer" - ], - "nodes": null + ] }, - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-stats.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-stats.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.usage.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.usage.json new file mode 100644 index 0000000000000..fbd55c82f68c0 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.usage.json @@ -0,0 +1,24 @@ +{ + "nodes.usage": { + "url_params": { + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_nodes/usage", + "_nodes/{nodes}/usage", + "_nodes/usage/{metrics}", + "_nodes/{nodes}/usage/{metrics}" + ], + "url_components": { + "nodes": null, + "metrics": [ + "_all", + "rest_actions" + ] + }, + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-usage.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/ping.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/ping.json new file mode 100644 index 0000000000000..bbc9036913248 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/ping.json @@ -0,0 +1,11 @@ +{ + "ping": { + "methods": [ + "HEAD" + ], + "patterns": [ + "" + ], + "documentation": "https://www.elastic.co/guide/" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/put_script.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/put_script.json new file mode 100644 index 0000000000000..f61d5b2404d0b --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/put_script.json @@ -0,0 +1,18 @@ +{ + "put_script": { + "url_params": { + "timeout": "", + "master_timeout": "", + "context": "" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "_scripts/{id}", + "_scripts/{id}/{context}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/rank_eval.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/rank_eval.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/rank_eval.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/rank_eval.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/reindex.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/reindex.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/reindex.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/reindex.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/reindex_rethrottle.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/reindex_rethrottle.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/reindex_rethrottle.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/reindex_rethrottle.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/render_search_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/render_search_template.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/render_search_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/render_search_template.json diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/scripts_painless_execute.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/scripts_painless_execute.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/scripts_painless_execute.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/scripts_painless_execute.json diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/scroll.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/scroll.json new file mode 100644 index 0000000000000..3e959b9630e98 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/scroll.json @@ -0,0 +1,18 @@ +{ + "scroll": { + "url_params": { + "scroll": "", + "scroll_id": "", + "rest_total_hits_as_int": "__flag__" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_search/scroll", + "_search/scroll/{scroll_id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-body.html#request-body-search-scroll" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/search.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/search.json similarity index 94% rename from src/legacy/core_plugins/console/api_server/spec/generated/search.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/search.json index 80aac6a62a106..eb21b43644d77 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/search.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/search.json @@ -67,6 +67,6 @@ "_search", "{indices}/_search" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-search.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-search.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/search_shards.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_shards.json similarity index 80% rename from src/legacy/core_plugins/console/api_server/spec/generated/search_shards.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/search_shards.json index af500f5994dae..cbeb0a429352d 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/search_shards.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_shards.json @@ -21,6 +21,6 @@ "_search_shards", "{indices}/_search_shards" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-shards.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-shards.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/search_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json similarity index 88% rename from src/legacy/core_plugins/console/api_server/spec/generated/search_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json index 26b1501a586e8..582ecab1dd614 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/search_template.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json @@ -33,6 +33,6 @@ "_search/template", "{indices}/_search/template" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.create.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.create.json new file mode 100644 index 0000000000000..0d5691d36cf5f --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.create.json @@ -0,0 +1,16 @@ +{ + "snapshot.create": { + "url_params": { + "master_timeout": "", + "wait_for_completion": "__flag__" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "_snapshot/{repository}/{snapshot}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.create_repository.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.create_repository.json new file mode 100644 index 0000000000000..c9e11195e754d --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.create_repository.json @@ -0,0 +1,17 @@ +{ + "snapshot.create_repository": { + "url_params": { + "master_timeout": "", + "timeout": "", + "verify": "__flag__" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "_snapshot/{repository}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.delete.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.delete.json new file mode 100644 index 0000000000000..f3c4f0b2bd1cd --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.delete.json @@ -0,0 +1,14 @@ +{ + "snapshot.delete": { + "url_params": { + "master_timeout": "" + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "_snapshot/{repository}/{snapshot}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.delete_repository.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.delete_repository.json new file mode 100644 index 0000000000000..8a35810e69e28 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.delete_repository.json @@ -0,0 +1,15 @@ +{ + "snapshot.delete_repository": { + "url_params": { + "master_timeout": "", + "timeout": "" + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "_snapshot/{repository}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.get.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.get.json new file mode 100644 index 0000000000000..b37141728f6b7 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.get.json @@ -0,0 +1,16 @@ +{ + "snapshot.get": { + "url_params": { + "master_timeout": "", + "ignore_unavailable": "__flag__", + "verbose": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_snapshot/{repository}/{snapshot}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.get_repository.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.get_repository.json new file mode 100644 index 0000000000000..4e8a2fa66bb60 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.get_repository.json @@ -0,0 +1,16 @@ +{ + "snapshot.get_repository": { + "url_params": { + "master_timeout": "", + "local": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_snapshot", + "_snapshot/{repository}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.restore.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.restore.json new file mode 100644 index 0000000000000..202f2a51e3b2f --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.restore.json @@ -0,0 +1,15 @@ +{ + "snapshot.restore": { + "url_params": { + "master_timeout": "", + "wait_for_completion": "__flag__" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_snapshot/{repository}/{snapshot}/_restore" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.status.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.status.json new file mode 100644 index 0000000000000..4b2fd6b85f3f9 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.status.json @@ -0,0 +1,17 @@ +{ + "snapshot.status": { + "url_params": { + "master_timeout": "", + "ignore_unavailable": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_snapshot/_status", + "_snapshot/{repository}/_status", + "_snapshot/{repository}/{snapshot}/_status" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.verify_repository.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.verify_repository.json new file mode 100644 index 0000000000000..23bd2ace35804 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/snapshot.verify_repository.json @@ -0,0 +1,15 @@ +{ + "snapshot.verify_repository": { + "url_params": { + "master_timeout": "", + "timeout": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_snapshot/{repository}/_verify" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.cancel.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.cancel.json new file mode 100644 index 0000000000000..7a84c6acb53a7 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.cancel.json @@ -0,0 +1,17 @@ +{ + "tasks.cancel": { + "url_params": { + "nodes": [], + "actions": [], + "parent_task_id": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_tasks/_cancel", + "_tasks/{task_id}/_cancel" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" + } +} diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.get.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.get.json new file mode 100644 index 0000000000000..8fcec99275f84 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.get.json @@ -0,0 +1,15 @@ +{ + "tasks.get": { + "url_params": { + "wait_for_completion": "__flag__", + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_tasks/{task_id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/tasks.list.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.list.json similarity index 79% rename from src/legacy/core_plugins/console/api_server/spec/generated/tasks.list.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.list.json index bf9142d236788..7218025e9cbf3 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/tasks.list.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/tasks.list.json @@ -19,6 +19,6 @@ "patterns": [ "_tasks" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" } } diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/termvectors.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/termvectors.json similarity index 84% rename from src/legacy/core_plugins/console/api_server/spec/generated/termvectors.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/termvectors.json index ba8af9f670506..d94cffc38b7af 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/termvectors.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/termvectors.json @@ -26,6 +26,6 @@ "{indices}/_termvectors/{id}", "{indices}/_termvectors" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-termvectors.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-termvectors.html" } } diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/update.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/update.json new file mode 100644 index 0000000000000..4e103b0af2195 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/update.json @@ -0,0 +1,29 @@ +{ + "update": { + "url_params": { + "wait_for_active_shards": "", + "_source": [], + "_source_excludes": [], + "_source_includes": [], + "lang": "painless", + "refresh": [ + "true", + "false", + "wait_for" + ], + "retry_on_conflict": "0", + "routing": "", + "timeout": "", + "if_seq_no": "", + "if_primary_term": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "{indices}/_update/{id}", + "{indices}/{type}/{id}/_update" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update.html" + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/update_by_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json similarity index 98% rename from src/legacy/core_plugins/console/api_server/spec/generated/update_by_query.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json index 393197949e86c..739ea16888146 100644 --- a/src/legacy/core_plugins/console/api_server/spec/generated/update_by_query.json +++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json @@ -32,7 +32,6 @@ "dfs_query_then_fetch" ], "search_timeout": "", - "size": "", "max_docs": "all documents", "sort": [], "_source": [], diff --git a/src/legacy/core_plugins/console/api_server/spec/generated/update_by_query_rethrottle.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query_rethrottle.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/generated/update_by_query_rethrottle.json rename to src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query_rethrottle.json diff --git a/src/legacy/core_plugins/console/api_server/spec/index.js b/src/legacy/core_plugins/console/server/api_server/spec/index.js similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/index.js rename to src/legacy/core_plugins/console/server/api_server/spec/index.js diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/cluster.health.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/cluster.health.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/cluster.health.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/cluster.health.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/cluster.put_settings.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/cluster.put_settings.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/cluster.put_settings.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/cluster.put_settings.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/cluster.reroute.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/cluster.reroute.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/cluster.reroute.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/cluster.reroute.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/count.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/count.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/count.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/count.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/create.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/create.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/create.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/create.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.analyze.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.analyze.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.analyze.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.analyze.json diff --git a/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.clone.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.clone.json new file mode 100644 index 0000000000000..d78491b7a49d2 --- /dev/null +++ b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.clone.json @@ -0,0 +1,14 @@ +{ + "indices.clone": { + "data_autocomplete_rules": { + "settings": { + "__scope_link": "put_settings" + }, + "aliases": { + "__template": { + "NAME": {} + } + } + } + } +} diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.create.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.create.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.create.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.create.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.delete_template.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.delete_template.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.delete_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.delete_template.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.exists_template.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.exists_template.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.exists_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.exists_template.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.get_field_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.get_field_mapping.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.get_field_mapping.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.get_field_mapping.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.get_mapping.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.get_mapping.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.get_mapping.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.get_mapping.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.get_template.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.get_template.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.get_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.get_template.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.put_alias.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.put_alias.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.put_alias.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.put_alias.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.put_settings.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.put_settings.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.put_settings.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.put_settings.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.put_template.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.put_template.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.put_template.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.put_template.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.rollover.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.rollover.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.rollover.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.rollover.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.update_aliases.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.update_aliases.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.update_aliases.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.update_aliases.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/indices.validate_query.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.validate_query.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/indices.validate_query.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/indices.validate_query.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/snapshot.create.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/snapshot.create.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/snapshot.create.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/snapshot.create.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/snapshot.create_repository.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/snapshot.create_repository.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/snapshot.create_repository.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/snapshot.create_repository.json diff --git a/src/legacy/core_plugins/console/api_server/spec/overrides/snapshot.restore.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/snapshot.restore.json similarity index 100% rename from src/legacy/core_plugins/console/api_server/spec/overrides/snapshot.restore.json rename to src/legacy/core_plugins/console/server/api_server/spec/overrides/snapshot.restore.json diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.test.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.test.tsx index 33471e172c589..7eb2f682e70ea 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.test.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.test.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { isErrorEmbeddable, EmbeddableFactory, GetEmbeddableFactory } from '../embeddable_api'; +import { isErrorEmbeddable, EmbeddableFactory } from '../embeddable_api'; import { ExpandPanelAction } from './expand_panel_action'; import { DashboardContainer } from '../embeddable'; import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers'; @@ -30,29 +30,39 @@ import { ContactCardEmbeddableInput, ContactCardEmbeddableOutput, } from '../../../../../../embeddable_api/public/np_ready/public/lib/test_samples/embeddables/contact_card/contact_card_embeddable'; +import { DashboardOptions } from '../embeddable/dashboard_container_factory'; -const __embeddableFactories = new Map(); -__embeddableFactories.set( +const embeddableFactories = new Map(); +embeddableFactories.set( CONTACT_CARD_EMBEDDABLE, new ContactCardEmbeddableFactory({} as any, (() => null) as any, {} as any) ); -const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => __embeddableFactories.get(id); let container: DashboardContainer; let embeddable: ContactCardEmbeddable; beforeEach(async () => { - container = new DashboardContainer( - getSampleDashboardInput({ - panels: { - '123': getSampleDashboardPanel({ - explicitInput: { firstName: 'Sam', id: '123' }, - type: CONTACT_CARD_EMBEDDABLE, - }), - }, - }), - { getEmbeddableFactory } as any - ); + const options: DashboardOptions = { + ExitFullScreenButton: () => null, + SavedObjectFinder: () => null, + application: {} as any, + embeddable: { + getEmbeddableFactory: (id: string) => embeddableFactories.get(id)!, + } as any, + inspector: {} as any, + notifications: {} as any, + overlays: {} as any, + savedObjectMetaData: {} as any, + }; + const input = getSampleDashboardInput({ + panels: { + '123': getSampleDashboardPanel({ + explicitInput: { firstName: 'Sam', id: '123' }, + type: CONTACT_CARD_EMBEDDABLE, + }), + }, + }); + container = new DashboardContainer(input, options); const contactCardEmbeddable = await container.addNewEmbeddable< ContactCardEmbeddableInput, diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.tsx index 273234cf8d8d5..494110750fcf3 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/expand_panel_action.tsx @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { Action, IEmbeddable, - ActionContext, IncompatibleActionError, } from '../../../../../../embeddable_api/public/np_ready/public'; import { DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '../embeddable'; @@ -40,7 +39,11 @@ function isExpanded(embeddable: IEmbeddable) { return embeddable.id === embeddable.parent.getInput().expandedPanelId; } -export class ExpandPanelAction extends Action { +interface ActionContext { + embeddable: IEmbeddable; +} + +export class ExpandPanelAction extends Action { public readonly type = EXPAND_PANEL_ACTION; constructor() { @@ -80,7 +83,7 @@ export class ExpandPanelAction extends Action { return Boolean(embeddable.parent && isDashboard(embeddable.parent)); } - public execute({ embeddable }: ActionContext) { + public async execute({ embeddable }: ActionContext) { if (!embeddable.parent || !isDashboard(embeddable.parent)) { throw new IncompatibleActionError(); } diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.test.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.test.tsx index b7dd29f28a724..d71088335c2ad 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.test.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.test.tsx @@ -21,7 +21,7 @@ import { findTestSubject } from '@elastic/eui/lib/test'; import { nextTick } from 'test_utils/enzyme_helpers'; import { isErrorEmbeddable, ViewMode, EmbeddableFactory } from '../embeddable_api'; -import { DashboardContainer, ViewportProps } from './dashboard_container'; +import { DashboardContainer, DashboardContainerOptions } from './dashboard_container'; import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers'; import { CONTACT_CARD_EMBEDDABLE, @@ -33,10 +33,13 @@ import { ContactCardEmbeddableOutput, } from '../../../../../../embeddable_api/public/np_ready/public/lib/test_samples/embeddables/contact_card/contact_card_embeddable'; -const viewportProps: ViewportProps = { - getActions: (() => []) as any, - getAllEmbeddableFactories: (() => []) as any, - getEmbeddableFactory: undefined as any, +const options: DashboardContainerOptions = { + application: {} as any, + embeddable: { + getTriggerCompatibleActions: (() => []) as any, + getEmbeddableFactories: (() => []) as any, + getEmbeddableFactory: undefined as any, + } as any, notifications: {} as any, overlays: {} as any, inspector: {} as any, @@ -45,26 +48,24 @@ const viewportProps: ViewportProps = { }; beforeEach(() => { - const __embeddableFactories = new Map(); - __embeddableFactories.set( + const embeddableFactories = new Map(); + embeddableFactories.set( CONTACT_CARD_EMBEDDABLE, new ContactCardEmbeddableFactory({} as any, (() => null) as any, {} as any) ); - viewportProps.getEmbeddableFactory = (id: string) => __embeddableFactories.get(id); + options.embeddable.getEmbeddableFactory = (id: string) => embeddableFactories.get(id) as any; }); test('DashboardContainer initializes embeddables', async done => { - const container = new DashboardContainer( - getSampleDashboardInput({ - panels: { - '123': getSampleDashboardPanel({ - explicitInput: { firstName: 'Sam', id: '123' }, - type: CONTACT_CARD_EMBEDDABLE, - }), - }, - }), - viewportProps - ); + const initialInput = getSampleDashboardInput({ + panels: { + '123': getSampleDashboardPanel({ + explicitInput: { firstName: 'Sam', id: '123' }, + type: CONTACT_CARD_EMBEDDABLE, + }), + }, + }); + const container = new DashboardContainer(initialInput, options); const subscription = container.getOutput$().subscribe(output => { if (container.getOutput().embeddableLoaded['123']) { @@ -85,7 +86,7 @@ test('DashboardContainer initializes embeddables', async done => { }); test('DashboardContainer.addNewEmbeddable', async () => { - const container = new DashboardContainer(getSampleDashboardInput(), viewportProps); + const container = new DashboardContainer(getSampleDashboardInput(), options); const embeddable = await container.addNewEmbeddable( CONTACT_CARD_EMBEDDABLE, { @@ -106,17 +107,15 @@ test('DashboardContainer.addNewEmbeddable', async () => { }); test('Container view mode change propagates to existing children', async () => { - const container = new DashboardContainer( - getSampleDashboardInput({ - panels: { - '123': getSampleDashboardPanel({ - explicitInput: { firstName: 'Sam', id: '123' }, - type: CONTACT_CARD_EMBEDDABLE, - }), - }, - }), - viewportProps - ); + const initialInput = getSampleDashboardInput({ + panels: { + '123': getSampleDashboardPanel({ + explicitInput: { firstName: 'Sam', id: '123' }, + type: CONTACT_CARD_EMBEDDABLE, + }), + }, + }); + const container = new DashboardContainer(initialInput, options); await nextTick(); const embeddable = await container.getChild('123'); @@ -126,7 +125,7 @@ test('Container view mode change propagates to existing children', async () => { }); test('Container view mode change propagates to new children', async () => { - const container = new DashboardContainer(getSampleDashboardInput(), viewportProps); + const container = new DashboardContainer(getSampleDashboardInput(), options); const embeddable = await container.addNewEmbeddable< ContactCardEmbeddableInput, ContactCardEmbeddableOutput, diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.tsx index 5fe414d12ccab..dc7aee514ab26 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container.tsx @@ -21,9 +21,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { I18nProvider } from '@kbn/i18n/react'; import { Filter } from '@kbn/es-query'; -import { CoreStart } from '../../../../../../../../core/public'; -import { RefreshInterval, TimeRange } from '../../../../../../../../plugins/data/public'; - +import { RefreshInterval, TimeRange } from 'src/plugins/data/public'; import { Container, ContainerInput, @@ -31,16 +29,20 @@ import { ViewMode, EmbeddableFactory, IEmbeddable, - GetEmbeddableFactory, - GetActionsCompatibleWithTrigger, - GetEmbeddableFactories, } from '../../../../../../embeddable_api/public/np_ready/public'; import { DASHBOARD_CONTAINER_TYPE } from './dashboard_container_factory'; import { createPanelState } from './panel'; import { DashboardPanelState } from './types'; import { DashboardViewport } from './viewport/dashboard_viewport'; import { Query } from '../../../../../../data/public'; +import { CoreStart } from '../../../../../../../../core/public'; import { Start as InspectorStartContract } from '../../../../../../../../plugins/inspector/public'; +import { Start as EmbeddableStartContract } from '../../../../../../embeddable_api/public/np_ready/public'; +import { + KibanaReactContext, + KibanaReactContextValue, + KibanaContextProvider, +} from '../../../../../../../../plugins/kibana_react/public'; export interface DashboardContainerInput extends ContainerInput { viewMode: ViewMode; @@ -72,23 +74,25 @@ export interface InheritedChildInput extends IndexSignature { id: string; } -export interface ViewportProps { - getActions: GetActionsCompatibleWithTrigger; - getEmbeddableFactory: GetEmbeddableFactory; - getAllEmbeddableFactories: GetEmbeddableFactories; +export interface DashboardContainerOptions { + application: CoreStart['application']; overlays: CoreStart['overlays']; notifications: CoreStart['notifications']; + embeddable: EmbeddableStartContract; inspector: InspectorStartContract; SavedObjectFinder: React.ComponentType; ExitFullScreenButton: React.ComponentType; } +export type DashboardReactContextValue = KibanaReactContextValue; +export type DashboardReactContext = KibanaReactContext; + export class DashboardContainer extends Container { public readonly type = DASHBOARD_CONTAINER_TYPE; constructor( initialInput: DashboardContainerInput, - private readonly viewportProps: ViewportProps, + private readonly options: DashboardContainerOptions, parent?: Container ) { super( @@ -100,7 +104,7 @@ export class DashboardContainer extends Container - + + + , dom ); diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container_factory.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container_factory.ts index f3cf7ae19823b..29ce9bcb0da2e 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container_factory.ts +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/dashboard_container_factory.ts @@ -20,25 +20,18 @@ import { i18n } from '@kbn/i18n'; import { SavedObjectAttributes } from '../../../../../../../../core/server'; import { SavedObjectMetaData } from '../types'; - +import { ContainerOutput, EmbeddableFactory, ErrorEmbeddable, Container } from '../embeddable_api'; import { - ContainerOutput, - EmbeddableFactory, - ErrorEmbeddable, - Container, - GetEmbeddableFactory, -} from '../embeddable_api'; -import { DashboardContainer, DashboardContainerInput, ViewportProps } from './dashboard_container'; + DashboardContainer, + DashboardContainerInput, + DashboardContainerOptions, +} from './dashboard_container'; +import { DashboardCapabilities } from '../types'; export const DASHBOARD_CONTAINER_TYPE = 'dashboard'; -export interface DashboardOptions { +export interface DashboardOptions extends DashboardContainerOptions { savedObjectMetaData?: SavedObjectMetaData; - capabilities: { - showWriteControls: boolean; - createNew: boolean; - }; - getFactory: GetEmbeddableFactory; } export class DashboardContainerFactory extends EmbeddableFactory< @@ -47,11 +40,20 @@ export class DashboardContainerFactory extends EmbeddableFactory< > { public readonly isContainerType = true; public readonly type = DASHBOARD_CONTAINER_TYPE; - private allowEditing: boolean; - constructor(options: DashboardOptions, private readonly containerOptions: ViewportProps) { + private readonly allowEditing: boolean; + + constructor(private readonly options: DashboardOptions) { super({ savedObjectMetaData: options.savedObjectMetaData }); - this.allowEditing = options.capabilities.createNew && options.capabilities.showWriteControls; + + const capabilities = (options.application.capabilities + .dashboard as unknown) as DashboardCapabilities; + + if (!capabilities || typeof capabilities !== 'object') { + throw new TypeError('Dashboard capabilities not found.'); + } + + this.allowEditing = !!capabilities.createNew && !!capabilities.showWriteControls; } public isEditable() { @@ -76,6 +78,6 @@ export class DashboardContainerFactory extends EmbeddableFactory< initialInput: DashboardContainerInput, parent?: Container ): Promise { - return new DashboardContainer(initialInput, this.containerOptions, parent); + return new DashboardContainer(initialInput, this.options, parent); } } diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.test.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.test.tsx index 8398d290bda6c..70eb59643ea08 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.test.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.test.tsx @@ -21,56 +21,65 @@ import sizeMe from 'react-sizeme'; import React from 'react'; -import { shallowWithIntl, nextTick, mountWithIntl } from 'test_utils/enzyme_helpers'; +import { nextTick, mountWithIntl } from 'test_utils/enzyme_helpers'; import { skip } from 'rxjs/operators'; import { EmbeddableFactory, GetEmbeddableFactory } from '../../embeddable_api'; import { DashboardGrid, DashboardGridProps } from './dashboard_grid'; -import { DashboardContainer } from '../dashboard_container'; +import { DashboardContainer, DashboardContainerOptions } from '../dashboard_container'; import { getSampleDashboardInput } from '../../test_helpers'; import { CONTACT_CARD_EMBEDDABLE, ContactCardEmbeddableFactory, } from '../../../../../../../embeddable_api/public/np_ready/public/lib/test_samples/embeddables/contact_card/contact_card_embeddable_factory'; +import { KibanaContextProvider } from '../../../../../../../../../plugins/kibana_react/public'; let dashboardContainer: DashboardContainer | undefined; -function getProps(props?: Partial): DashboardGridProps { - const __embeddableFactories = new Map(); - __embeddableFactories.set( +function prepare(props?: Partial) { + const embeddableFactories = new Map(); + embeddableFactories.set( CONTACT_CARD_EMBEDDABLE, new ContactCardEmbeddableFactory({} as any, (() => {}) as any, {} as any) ); - const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => __embeddableFactories.get(id); - - dashboardContainer = new DashboardContainer( - getSampleDashboardInput({ - panels: { - '1': { - gridData: { x: 0, y: 0, w: 6, h: 6, i: '1' }, - type: CONTACT_CARD_EMBEDDABLE, - explicitInput: { id: '1' }, - }, - '2': { - gridData: { x: 6, y: 6, w: 6, h: 6, i: '2' }, - type: CONTACT_CARD_EMBEDDABLE, - explicitInput: { id: '2' }, - }, + const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id); + const initialInput = getSampleDashboardInput({ + panels: { + '1': { + gridData: { x: 0, y: 0, w: 6, h: 6, i: '1' }, + type: CONTACT_CARD_EMBEDDABLE, + explicitInput: { id: '1' }, }, - }), - { getEmbeddableFactory } as any - ); - const defaultTestProps: DashboardGridProps = { - container: dashboardContainer, - intl: null as any, - getActions: (() => []) as any, - getAllEmbeddableFactories: (() => []) as any, - getEmbeddableFactory: (() => {}) as any, + '2': { + gridData: { x: 6, y: 6, w: 6, h: 6, i: '2' }, + type: CONTACT_CARD_EMBEDDABLE, + explicitInput: { id: '2' }, + }, + }, + }); + const options: DashboardContainerOptions = { + application: {} as any, + embeddable: { + getTriggerCompatibleActions: (() => []) as any, + getEmbeddableFactories: (() => []) as any, + getEmbeddableFactory, + } as any, notifications: {} as any, overlays: {} as any, inspector: {} as any, SavedObjectFinder: () => null, + ExitFullScreenButton: () => null, + }; + dashboardContainer = new DashboardContainer(initialInput, options); + const defaultTestProps: DashboardGridProps = { + container: dashboardContainer, + kibana: null as any, + intl: null as any, + }; + + return { + props: Object.assign(defaultTestProps, props), + options, }; - return Object.assign(defaultTestProps, props); } beforeAll(() => { @@ -84,55 +93,85 @@ afterAll(() => { }); test('renders DashboardGrid', () => { - const component = shallowWithIntl(); - const panelElements = component.find('InjectIntl(EmbeddableChildPanelUi)'); + const { props, options } = prepare(); + const component = mountWithIntl( + + + + ); + + const panelElements = component.find('EmbeddableChildPanel'); expect(panelElements.length).toBe(2); }); test('renders DashboardGrid with no visualizations', async () => { - const props = getProps(); - const component = shallowWithIntl(); + const { props, options } = prepare(); + const component = mountWithIntl( + + + + ); + props.container.updateInput({ panels: {} }); await nextTick(); component.update(); - expect(component.find('InjectIntl(EmbeddableChildPanelUi)').length).toBe(0); + expect(component.find('EmbeddableChildPanel').length).toBe(0); }); test('DashboardGrid removes panel when removed from container', async () => { - const props = getProps(); - const component = shallowWithIntl(); + const { props, options } = prepare(); + const component = mountWithIntl( + + + + ); + const originalPanels = props.container.getInput().panels; const filteredPanels = { ...originalPanels }; delete filteredPanels['1']; props.container.updateInput({ panels: filteredPanels }); await nextTick(); component.update(); - const panelElements = component.find('InjectIntl(EmbeddableChildPanelUi)'); + const panelElements = component.find('EmbeddableChildPanel'); expect(panelElements.length).toBe(1); }); test('DashboardGrid renders expanded panel', async () => { - const props = getProps(); - const component = shallowWithIntl(); + const { props, options } = prepare(); + const component = mountWithIntl( + + + + ); + props.container.updateInput({ expandedPanelId: '1' }); await nextTick(); component.update(); // Both panels should still exist in the dom, so nothing needs to be re-fetched once minimized. - expect(component.find('InjectIntl(EmbeddableChildPanelUi)').length).toBe(2); + expect(component.find('EmbeddableChildPanel').length).toBe(2); - expect((component.state() as { expandedPanelId?: string }).expandedPanelId).toBe('1'); + expect( + (component.find('DashboardGridUi').state() as { expandedPanelId?: string }).expandedPanelId + ).toBe('1'); props.container.updateInput({ expandedPanelId: undefined }); await nextTick(); component.update(); - expect(component.find('InjectIntl(EmbeddableChildPanelUi)').length).toBe(2); + expect(component.find('EmbeddableChildPanel').length).toBe(2); - expect((component.state() as { expandedPanelId?: string }).expandedPanelId).toBeUndefined(); + expect( + (component.find('DashboardGridUi').state() as { expandedPanelId?: string }).expandedPanelId + ).toBeUndefined(); }); test('DashboardGrid unmount unsubscribes', async done => { - const props = getProps(); - const component = mountWithIntl(); + const { props, options } = prepare(); + const component = mountWithIntl( + + + + ); + component.unmount(); props.container diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.tsx index cbd10b8b493c4..d34a88c474e38 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/grid/dashboard_grid.tsx @@ -28,17 +28,11 @@ import { Subscription } from 'rxjs'; import ReactGridLayout, { Layout } from 'react-grid-layout'; // @ts-ignore import sizeMe from 'react-sizeme'; -import { - GetActionsCompatibleWithTrigger, - GetEmbeddableFactory, - GetEmbeddableFactories, -} from 'src/legacy/core_plugins/embeddable_api/public/np_ready/public'; -import { CoreStart } from 'src/core/public'; import { ViewMode, EmbeddableChildPanel } from '../../embeddable_api'; import { DASHBOARD_GRID_COLUMN_COUNT, DASHBOARD_GRID_HEIGHT } from '../dashboard_constants'; -import { DashboardContainer } from '../dashboard_container'; +import { DashboardContainer, DashboardReactContextValue } from '../dashboard_container'; import { DashboardPanelState, GridData } from '../types'; -import { Start as InspectorStartContract } from '../../../../../../../../../plugins/inspector/public'; +import { withKibana } from '../../../../../../../../../plugins/kibana_react/public'; let lastValidGridSize = 0; @@ -117,14 +111,8 @@ const config = { monitorWidth: true }; const ResponsiveSizedGrid = sizeMe(config)(ResponsiveGrid); export interface DashboardGridProps extends ReactIntl.InjectedIntlProps { + kibana: DashboardReactContextValue; container: DashboardContainer; - getActions: GetActionsCompatibleWithTrigger; - getEmbeddableFactory: GetEmbeddableFactory; - getAllEmbeddableFactories: GetEmbeddableFactories; - overlays: CoreStart['overlays']; - notifications: CoreStart['notifications']; - inspector: InspectorStartContract; - SavedObjectFinder: React.ComponentType; } interface State { @@ -172,12 +160,13 @@ class DashboardGridUi extends React.Component { console.error(error); // eslint-disable-line no-console isLayoutInvalid = true; - this.props.notifications.toasts.addDanger({ + this.props.kibana.notifications.toasts.danger({ title: this.props.intl.formatMessage({ id: 'dashboardEmbeddableContainer.dashboardGrid.toast.unableToLoadDashboardDangerMessage', defaultMessage: 'Unable to load dashboard.', }), - text: error.message, + body: error.message, + toastLifeTimeMs: 5000, }); } this.setState({ @@ -241,7 +230,7 @@ class DashboardGridUi extends React.Component { } }; - public renderDOM() { + public renderPanels() { const { focusedPanelIndex, panels, expandedPanelId } = this.state; // Part of our unofficial API - need to render in a consistent order for plugins. @@ -277,13 +266,13 @@ class DashboardGridUi extends React.Component {
    ); @@ -305,10 +294,10 @@ class DashboardGridUi extends React.Component { maximizedPanelId={this.state.expandedPanelId} useMargins={this.state.useMargins} > - {this.renderDOM()} + {this.renderPanels()} ); } } -export const DashboardGrid = injectI18n(DashboardGridUi); +export const DashboardGrid = injectI18n(withKibana(DashboardGridUi)); diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.test.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.test.tsx index 56c37fa6fea54..ef7b1c9e5215f 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.test.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.test.tsx @@ -26,22 +26,34 @@ import { I18nProvider } from '@kbn/i18n/react'; import { nextTick } from 'test_utils/enzyme_helpers'; import { EmbeddableFactory } from '../../embeddable_api'; import { DashboardViewport, DashboardViewportProps } from './dashboard_viewport'; -import { DashboardContainer, ViewportProps } from '../dashboard_container'; +import { DashboardContainer, DashboardContainerOptions } from '../dashboard_container'; import { getSampleDashboardInput } from '../../test_helpers'; import { CONTACT_CARD_EMBEDDABLE, ContactCardEmbeddableFactory, } from '../../../../../../../embeddable_api/public/np_ready/public/lib/test_samples/embeddables/contact_card/contact_card_embeddable_factory'; +import { KibanaContextProvider } from '../../../../../../../../../plugins/kibana_react/public'; let dashboardContainer: DashboardContainer | undefined; const ExitFullScreenButton = () =>
    EXIT
    ; -function getProps(props?: Partial): DashboardViewportProps { - const viewportProps: ViewportProps = { - getActions: (() => []) as any, - getAllEmbeddableFactories: (() => []) as any, - getEmbeddableFactory: undefined as any, +function getProps( + props?: Partial +): { props: DashboardViewportProps; options: DashboardContainerOptions } { + const embeddableFactories = new Map(); + embeddableFactories.set( + CONTACT_CARD_EMBEDDABLE, + new ContactCardEmbeddableFactory({}, (() => null) as any, {} as any) + ); + + const options: DashboardContainerOptions = { + application: {} as any, + embeddable: { + getTriggerCompatibleActions: (() => []) as any, + getEmbeddableFactories: (() => []) as any, + getEmbeddableFactory: (id: string) => embeddableFactories.get(id), + } as any, notifications: {} as any, overlays: {} as any, inspector: {} as any, @@ -49,44 +61,39 @@ function getProps(props?: Partial): DashboardViewportPro ExitFullScreenButton, }; - const __embeddableFactories = new Map(); - __embeddableFactories.set( - CONTACT_CARD_EMBEDDABLE, - new ContactCardEmbeddableFactory({}, (() => null) as any, {} as any) - ); - viewportProps.getEmbeddableFactory = (id: string) => __embeddableFactories.get(id); - - dashboardContainer = new DashboardContainer( - getSampleDashboardInput({ - panels: { - '1': { - gridData: { x: 0, y: 0, w: 6, h: 6, i: '1' }, - type: CONTACT_CARD_EMBEDDABLE, - explicitInput: { id: '1' }, - }, - '2': { - gridData: { x: 6, y: 6, w: 6, h: 6, i: '2' }, - type: CONTACT_CARD_EMBEDDABLE, - explicitInput: { id: '2' }, - }, + const input = getSampleDashboardInput({ + panels: { + '1': { + gridData: { x: 0, y: 0, w: 6, h: 6, i: '1' }, + type: CONTACT_CARD_EMBEDDABLE, + explicitInput: { id: '1' }, }, - }), - viewportProps - ); + '2': { + gridData: { x: 6, y: 6, w: 6, h: 6, i: '2' }, + type: CONTACT_CARD_EMBEDDABLE, + explicitInput: { id: '2' }, + }, + }, + }); + + dashboardContainer = new DashboardContainer(input, options); const defaultTestProps: DashboardViewportProps = { container: dashboardContainer, - ...viewportProps, - inspector: {} as any, - ExitFullScreenButton: () => null, }; - return Object.assign(defaultTestProps, props); + + return { + props: Object.assign(defaultTestProps, props), + options, + }; } test('renders DashboardViewport', () => { - const props = getProps(); + const { props, options } = getProps(); const component = mount( - + + + ); const panels = findTestSubject(component, 'dashboardPanel'); @@ -94,11 +101,13 @@ test('renders DashboardViewport', () => { }); test('renders DashboardViewport with no visualizations', () => { - const props = getProps(); + const { props, options } = getProps(); props.container.updateInput({ panels: {} }); const component = mount( - + + + ); const panels = findTestSubject(component, 'dashboardPanel'); @@ -108,11 +117,13 @@ test('renders DashboardViewport with no visualizations', () => { }); test('renders exit full screen button when in full screen mode', async () => { - const props = getProps(); + const { props, options } = getProps(); props.container.updateInput({ isFullScreenMode: true }); const component = mount( - + + + ); @@ -138,10 +149,12 @@ test('renders exit full screen button when in full screen mode', async () => { }); test('DashboardViewport unmount unsubscribes', async done => { - const props = getProps(); + const { props, options } = getProps(); const component = mount( - + + + ); component.unmount(); diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.tsx index aee52fa6d7d38..59accb225238b 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/embeddable/viewport/dashboard_viewport.tsx @@ -19,27 +19,13 @@ import React from 'react'; import { Subscription } from 'rxjs'; -import { - GetActionsCompatibleWithTrigger, - GetEmbeddableFactory, - GetEmbeddableFactories, -} from 'src/legacy/core_plugins/embeddable_api/public/np_ready/public'; -import { CoreStart } from 'src/core/public'; import { PanelState } from '../../embeddable_api'; -import { DashboardContainer } from '../dashboard_container'; +import { DashboardContainer, DashboardReactContextValue } from '../dashboard_container'; import { DashboardGrid } from '../grid'; -import { Start as InspectorStartContract } from '../../../../../../../../../plugins/inspector/public'; +import { context } from '../../../../../../../../../plugins/kibana_react/public'; export interface DashboardViewportProps { container: DashboardContainer; - getActions: GetActionsCompatibleWithTrigger; - getEmbeddableFactory: GetEmbeddableFactory; - getAllEmbeddableFactories: GetEmbeddableFactories; - overlays: CoreStart['overlays']; - notifications: CoreStart['notifications']; - inspector: InspectorStartContract; - SavedObjectFinder: React.ComponentType; - ExitFullScreenButton: React.ComponentType; } interface State { @@ -51,6 +37,9 @@ interface State { } export class DashboardViewport extends React.Component { + static contextType = context; + + public readonly context!: DashboardReactContextValue; private subscription?: Subscription; private mounted: boolean = false; constructor(props: DashboardViewportProps) { @@ -106,18 +95,11 @@ export class DashboardViewport extends React.Component {this.state.isFullScreenMode && ( - + )} - +
    ); } diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts index a11637beb2ee4..350def9833732 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts @@ -19,7 +19,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { CONTEXT_MENU_TRIGGER, Plugin as EmbeddablePlugin } from './lib/embeddable_api'; -import { ExpandPanelAction, DashboardContainerFactory, DashboardCapabilities } from './lib'; +import { ExpandPanelAction, DashboardContainerFactory } from './lib'; import { Start as InspectorStartContract } from '../../../../../../plugins/inspector/public'; interface SetupDependencies { @@ -52,16 +52,11 @@ export class DashboardEmbeddableContainerPublicPlugin const { application, notifications, overlays } = core; const { embeddable, inspector, __LEGACY } = plugins; - const dashboardOptions = { - capabilities: (application.capabilities.dashboard as unknown) as DashboardCapabilities, - getFactory: embeddable.getEmbeddableFactory, - }; - const factory = new DashboardContainerFactory(dashboardOptions, { - getActions: embeddable.getTriggerCompatibleActions, - getAllEmbeddableFactories: embeddable.getEmbeddableFactories, - getEmbeddableFactory: embeddable.getEmbeddableFactory, + const factory = new DashboardContainerFactory({ + application, notifications, overlays, + embeddable, inspector, SavedObjectFinder: __LEGACY.SavedObjectFinder, ExitFullScreenButton: __LEGACY.ExitFullScreenButton, diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/tests/dashboard_container.test.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/tests/dashboard_container.test.tsx index b70da90b046c4..e19d95aefe770 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/tests/dashboard_container.test.tsx +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/tests/dashboard_container.test.tsx @@ -24,7 +24,10 @@ import { mount } from 'enzyme'; import { nextTick } from 'test_utils/enzyme_helpers'; import { I18nProvider } from '@kbn/i18n/react'; import { ViewMode, CONTEXT_MENU_TRIGGER, EmbeddablePanel } from '../lib/embeddable_api'; -import { DashboardContainer } from '../lib/embeddable/dashboard_container'; +import { + DashboardContainer, + DashboardContainerOptions, +} from '../lib/embeddable/dashboard_container'; import { getSampleDashboardInput } from '../lib/test_helpers'; import { CONTACT_CARD_EMBEDDABLE, @@ -39,6 +42,7 @@ import { embeddablePluginMock } from '../../../../../embeddable_api/public/np_re import { EditModeAction } from '../../../../../embeddable_api/public/np_ready/public/lib/test_samples/actions/edit_mode_action'; // eslint-disable-next-line import { inspectorPluginMock } from '../../../../../../../plugins/inspector/public/mocks'; +import { KibanaContextProvider } from '../../../../../../../plugins/kibana_react/public'; test('DashboardContainer in edit mode shows edit mode actions', async () => { const inspector = inspectorPluginMock.createStartContract(); @@ -54,9 +58,17 @@ test('DashboardContainer in edit mode shows edit mode actions', async () => { const start = doStart(); - const container = new DashboardContainer(getSampleDashboardInput({ viewMode: ViewMode.VIEW }), { - getEmbeddableFactory: start.getEmbeddableFactory, - } as any); + const initialInput = getSampleDashboardInput({ viewMode: ViewMode.VIEW }); + const options: DashboardContainerOptions = { + application: {} as any, + embeddable: start, + notifications: {} as any, + overlays: {} as any, + inspector: {} as any, + SavedObjectFinder: () => null, + ExitFullScreenButton: () => null, + }; + const container = new DashboardContainer(initialInput, options); const embeddable = await container.addNewEmbeddable< ContactCardEmbeddableInput, @@ -68,16 +80,18 @@ test('DashboardContainer in edit mode shows edit mode actions', async () => { const component = mount( - []) as any} - getAllEmbeddableFactories={(() => []) as any} - getEmbeddableFactory={(() => null) as any} - notifications={{} as any} - overlays={{} as any} - inspector={inspector} - SavedObjectFinder={() => null} - /> + + Promise.resolve([])} + getAllEmbeddableFactories={(() => []) as any} + getEmbeddableFactory={(() => null) as any} + notifications={{} as any} + overlays={{} as any} + inspector={inspector} + SavedObjectFinder={() => null} + /> + ); diff --git a/src/legacy/core_plugins/data/index.ts b/src/legacy/core_plugins/data/index.ts index 0557fd82edbc8..a985d3f023108 100644 --- a/src/legacy/core_plugins/data/index.ts +++ b/src/legacy/core_plugins/data/index.ts @@ -19,6 +19,8 @@ import { resolve } from 'path'; import { Legacy } from '../../../../kibana'; +import { mappings } from './mappings'; +import { SavedQuery } from './public'; // eslint-disable-next-line import/no-default-export export default function DataPlugin(kibana: any) { @@ -35,6 +37,23 @@ export default function DataPlugin(kibana: any) { uiExports: { injectDefaultVars: () => ({}), styleSheetPaths: resolve(__dirname, 'public/index.scss'), + mappings, + savedObjectsManagement: { + query: { + icon: 'search', + defaultSearchField: 'title', + isImportableAndExportable: true, + getTitle(obj: SavedQuery) { + return obj.attributes.title; + }, + getInAppUrl(obj: SavedQuery) { + return { + path: `/app/kibana#/discover?_a=(savedQuery:'${encodeURIComponent(obj.id)}')`, + uiCapabilitiesPath: 'discover.show', + }; + }, + }, + }, }, }; diff --git a/src/legacy/core_plugins/data/mappings.ts b/src/legacy/core_plugins/data/mappings.ts new file mode 100644 index 0000000000000..90777ec8e3651 --- /dev/null +++ b/src/legacy/core_plugins/data/mappings.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. + */ + +export const mappings = { + query: { + properties: { + title: { + type: 'text', + }, + description: { + type: 'text', + }, + query: { + properties: { + language: { + type: 'keyword', + }, + query: { + type: 'keyword', + index: false, + }, + }, + }, + filters: { + type: 'object', + enabled: false, + }, + timefilter: { + type: 'object', + enabled: false, + }, + }, + }, +}; diff --git a/src/legacy/core_plugins/data/public/expressions/expression_renderer.tsx b/src/legacy/core_plugins/data/public/expressions/expression_renderer.tsx deleted file mode 100644 index 310a3b11a8456..0000000000000 --- a/src/legacy/core_plugins/data/public/expressions/expression_renderer.tsx +++ /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 { useRef, useEffect } from 'react'; -import React from 'react'; -import { Ast } from '@kbn/interpreter/common'; - -import { ExpressionRunnerOptions, ExpressionRunner } from './expression_runner'; -import { Result } from './expressions_service'; - -// Accept all options of the runner as props except for the -// dom element which is provided by the component itself -export type ExpressionRendererProps = Pick< - ExpressionRunnerOptions, - Exclude -> & { - expression: string | Ast; - /** - * If an element is specified, but the response of the expression run can't be rendered - * because it isn't a valid response or the specified renderer isn't available, - * this callback is called with the given result. - */ - onRenderFailure?: (result: Result) => void; -}; - -export type ExpressionRenderer = React.FC; - -export const createRenderer = (run: ExpressionRunner): ExpressionRenderer => ({ - expression, - onRenderFailure, - ...options -}: ExpressionRendererProps) => { - const mountpoint: React.MutableRefObject = useRef(null); - - useEffect(() => { - if (mountpoint.current) { - run(expression, { ...options, element: mountpoint.current }).catch(result => { - if (onRenderFailure) { - onRenderFailure(result); - } - }); - } - }, [expression, mountpoint.current]); - - return ( -
    { - mountpoint.current = el; - }} - /> - ); -}; diff --git a/src/legacy/core_plugins/data/public/expressions/expression_runner.ts b/src/legacy/core_plugins/data/public/expressions/expression_runner.ts deleted file mode 100644 index bfad401ae8620..0000000000000 --- a/src/legacy/core_plugins/data/public/expressions/expression_runner.ts +++ /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 { Ast, fromExpression } from '@kbn/interpreter/common'; - -import { RequestAdapter, DataAdapter } from 'ui/inspector/adapters'; -import { RenderFunctionsRegistry, Interpreter, Result } from './expressions_service'; - -export interface ExpressionRunnerOptions { - // TODO use the real types here once they are ready - context?: object; - getInitialContext?: () => object; - element?: Element; -} - -export type ExpressionRunner = ( - expression: string | Ast, - options: ExpressionRunnerOptions -) => Promise; - -export const createRunFn = ( - renderersRegistry: RenderFunctionsRegistry, - interpreterPromise: Promise -): ExpressionRunner => async (expressionOrAst, { element, context, getInitialContext }) => { - // TODO: make interpreter initialization synchronous to avoid this - const interpreter = await interpreterPromise; - const ast = - typeof expressionOrAst === 'string' ? fromExpression(expressionOrAst) : expressionOrAst; - - const response = await interpreter.interpretAst(ast, context || { type: 'null' }, { - getInitialContext: getInitialContext || (() => ({})), - inspectorAdapters: { - // TODO connect real adapters - requests: new RequestAdapter(), - data: new DataAdapter(), - }, - }); - - if (response.type === 'error') { - throw response; - } - - if (element) { - if (response.type === 'render' && response.as && renderersRegistry.get(response.as) !== null) { - renderersRegistry.get(response.as).render(element, response.value, { - onDestroy: fn => { - // TODO implement - }, - done: () => { - // TODO implement - }, - }); - } else { - throw response; - } - } - - return response; -}; diff --git a/src/legacy/core_plugins/data/public/expressions/expressions_service.test.tsx b/src/legacy/core_plugins/data/public/expressions/expressions_service.test.tsx deleted file mode 100644 index 83313e5a2b2fe..0000000000000 --- a/src/legacy/core_plugins/data/public/expressions/expressions_service.test.tsx +++ /dev/null @@ -1,276 +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 { fromExpression, Ast } from '@kbn/interpreter/common'; - -import { - ExpressionsService, - RenderFunctionsRegistry, - RenderFunction, - Interpreter, - ExpressionsServiceDependencies, - Result, - ExpressionsSetup, -} from './expressions_service'; -import { mount } from 'enzyme'; -import React from 'react'; - -const waitForInterpreterRun = async () => { - // Wait for two ticks with empty callback queues - // This makes sure the runFn promise and actual interpretAst - // promise have been resolved and processed - await new Promise(resolve => setTimeout(resolve)); - await new Promise(resolve => setTimeout(resolve)); -}; - -const RENDERER_ID = 'mockId'; - -describe('expressions_service', () => { - let interpretAstMock: jest.Mocked['interpretAst']; - let interpreterMock: jest.Mocked; - let renderFunctionMock: jest.Mocked; - let setupPluginsMock: ExpressionsServiceDependencies; - const expressionResult: Result = { type: 'render', as: RENDERER_ID, value: {} }; - - let api: ExpressionsSetup; - let testExpression: string; - let testAst: Ast; - - beforeEach(() => { - interpretAstMock = jest.fn((..._) => Promise.resolve(expressionResult)); - interpreterMock = { interpretAst: interpretAstMock }; - renderFunctionMock = ({ - render: jest.fn(), - } as unknown) as jest.Mocked; - setupPluginsMock = { - interpreter: { - getInterpreter: () => Promise.resolve({ interpreter: interpreterMock }), - renderersRegistry: ({ - get: (id: string) => (id === RENDERER_ID ? renderFunctionMock : null), - } as unknown) as RenderFunctionsRegistry, - }, - }; - api = new ExpressionsService().setup(setupPluginsMock); - testExpression = 'test | expression'; - testAst = fromExpression(testExpression); - }); - - describe('expression_runner', () => { - it('should return run function', () => { - expect(typeof api.run).toBe('function'); - }); - - it('should call the interpreter with parsed expression', async () => { - await api.run(testExpression, { element: document.createElement('div') }); - expect(interpreterMock.interpretAst).toHaveBeenCalledWith( - testAst, - expect.anything(), - expect.anything() - ); - }); - - it('should call the interpreter with given context and getInitialContext functions', async () => { - const getInitialContext = () => ({}); - const context = {}; - - await api.run(testExpression, { getInitialContext, context }); - const interpretCall = interpreterMock.interpretAst.mock.calls[0]; - - expect(interpretCall[1]).toBe(context); - expect(interpretCall[2].getInitialContext).toBe(getInitialContext); - }); - - it('should call the interpreter with passed in ast', async () => { - await api.run(testAst, { element: document.createElement('div') }); - expect(interpreterMock.interpretAst).toHaveBeenCalledWith( - testAst, - expect.anything(), - expect.anything() - ); - }); - - it('should return the result of the interpreter run', async () => { - const response = await api.run(testAst, {}); - expect(response).toBe(expressionResult); - }); - - it('should reject the promise if the response is not renderable but an element is passed', async () => { - const unexpectedResult = { type: 'datatable', value: {} }; - interpretAstMock.mockReturnValue(Promise.resolve(unexpectedResult)); - expect( - api.run(testAst, { - element: document.createElement('div'), - }) - ).rejects.toBe(unexpectedResult); - }); - - it('should reject the promise if the renderer is not known', async () => { - const unexpectedResult = { type: 'render', as: 'unknown_id' }; - interpretAstMock.mockReturnValue(Promise.resolve(unexpectedResult)); - expect( - api.run(testAst, { - element: document.createElement('div'), - }) - ).rejects.toBe(unexpectedResult); - }); - - it('should not reject the promise on unknown renderer if the runner is not rendering', async () => { - const unexpectedResult = { type: 'render', as: 'unknown_id' }; - interpretAstMock.mockReturnValue(Promise.resolve(unexpectedResult)); - expect(api.run(testAst, {})).resolves.toBe(unexpectedResult); - }); - - it('should reject the promise if the response is an error', async () => { - const errorResult = { type: 'error', error: {} }; - interpretAstMock.mockReturnValue(Promise.resolve(errorResult)); - expect(api.run(testAst, {})).rejects.toBe(errorResult); - }); - - it('should reject the promise if there are syntax errors', async () => { - expect(api.run('|||', {})).rejects.toBeInstanceOf(Error); - }); - - it('should call the render function with the result and element', async () => { - const element = document.createElement('div'); - - await api.run(testAst, { element }); - expect(renderFunctionMock.render).toHaveBeenCalledWith( - element, - expressionResult.value, - expect.anything() - ); - expect(interpreterMock.interpretAst).toHaveBeenCalledWith( - testAst, - expect.anything(), - expect.anything() - ); - }); - }); - - describe('expression_renderer', () => { - it('should call interpreter and render function when called through react component', async () => { - const ExpressionRenderer = api.ExpressionRenderer; - - mount(); - - await waitForInterpreterRun(); - - expect(renderFunctionMock.render).toHaveBeenCalledWith( - expect.any(Element), - expressionResult.value, - expect.anything() - ); - expect(interpreterMock.interpretAst).toHaveBeenCalledWith( - testAst, - expect.anything(), - expect.anything() - ); - }); - - it('should call the interpreter with given context and getInitialContext functions', async () => { - const getInitialContext = () => ({}); - const context = {}; - - const ExpressionRenderer = api.ExpressionRenderer; - - mount( - - ); - - await waitForInterpreterRun(); - - const interpretCall = interpreterMock.interpretAst.mock.calls[0]; - - expect(interpretCall[1]).toBe(context); - expect(interpretCall[2].getInitialContext).toBe(getInitialContext); - }); - - it('should call interpreter and render function again if expression changes', async () => { - const ExpressionRenderer = api.ExpressionRenderer; - - const instance = mount(); - - await waitForInterpreterRun(); - - expect(renderFunctionMock.render).toHaveBeenCalledWith( - expect.any(Element), - expressionResult.value, - expect.anything() - ); - expect(interpreterMock.interpretAst).toHaveBeenCalledWith( - testAst, - expect.anything(), - expect.anything() - ); - - instance.setProps({ expression: 'supertest | expression ' }); - - await waitForInterpreterRun(); - - expect(renderFunctionMock.render).toHaveBeenCalledTimes(2); - expect(interpreterMock.interpretAst).toHaveBeenCalledTimes(2); - }); - - it('should not call interpreter and render function again if expression does not change', async () => { - const ast = fromExpression(testExpression); - - const ExpressionRenderer = api.ExpressionRenderer; - - const instance = mount(); - - await waitForInterpreterRun(); - - expect(renderFunctionMock.render).toHaveBeenCalledWith( - expect.any(Element), - expressionResult.value, - expect.anything() - ); - expect(interpreterMock.interpretAst).toHaveBeenCalledWith( - ast, - expect.anything(), - expect.anything() - ); - - instance.update(); - - await waitForInterpreterRun(); - - expect(renderFunctionMock.render).toHaveBeenCalledTimes(1); - expect(interpreterMock.interpretAst).toHaveBeenCalledTimes(1); - }); - - it('should call onRenderFailure if the result can not be rendered', async () => { - const errorResult = { type: 'error', error: {} }; - interpretAstMock.mockReturnValue(Promise.resolve(errorResult)); - const renderFailureSpy = jest.fn(); - - const ExpressionRenderer = api.ExpressionRenderer; - - mount(); - - await waitForInterpreterRun(); - - expect(renderFailureSpy).toHaveBeenCalledWith(errorResult); - }); - }); -}); diff --git a/src/legacy/core_plugins/data/public/expressions/expressions_service.ts b/src/legacy/core_plugins/data/public/expressions/expressions_service.ts deleted file mode 100644 index f5d2163cae863..0000000000000 --- a/src/legacy/core_plugins/data/public/expressions/expressions_service.ts +++ /dev/null @@ -1,130 +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 { Ast } from '@kbn/interpreter/common'; - -// TODO: -// this type import and the types below them should be switched to the types of -// the interpreter plugin itself once they are ready -import { Registry } from '@kbn/interpreter/common'; -import { Adapters } from 'ui/inspector'; -import { Filter } from '@kbn/es-query'; -import { TimeRange } from '../../../../../plugins/data/public'; -import { createRenderer } from './expression_renderer'; -import { createRunFn } from './expression_runner'; -import { Query } from '../query'; - -export interface InitialContextObject { - timeRange?: TimeRange; - filters?: Filter[]; - query?: Query; -} - -export type getInitialContextFunction = () => InitialContextObject; - -export interface Handlers { - getInitialContext: getInitialContextFunction; - inspectorAdapters?: Adapters; - abortSignal?: AbortSignal; -} - -type Context = object; -export interface Result { - type: string; - as?: string; - value?: unknown; - error?: unknown; -} - -interface RenderHandlers { - done: () => void; - onDestroy: (fn: () => void) => void; -} - -export interface RenderFunction { - name: string; - displayName: string; - help: string; - validate: () => void; - reuseDomNode: boolean; - render: (domNode: Element, data: unknown, handlers: RenderHandlers) => void; -} - -export type RenderFunctionsRegistry = Registry; - -export interface Interpreter { - interpretAst(ast: Ast, context: Context, handlers: Handlers): Promise; -} - -type InterpreterGetter = () => Promise<{ interpreter: Interpreter }>; - -export interface ExpressionsServiceDependencies { - interpreter: { - renderersRegistry: RenderFunctionsRegistry; - getInterpreter: InterpreterGetter; - }; -} - -/** - * Expressions Service - * @internal - */ -export class ExpressionsService { - public setup({ - interpreter: { renderersRegistry, getInterpreter }, - }: ExpressionsServiceDependencies) { - const run = createRunFn( - renderersRegistry, - getInterpreter().then(({ interpreter }) => interpreter) - ); - - return { - /** - * **experimential** This API is experimential and might be removed in the future - * without notice - * - * Executes the given expression string or ast and renders the result into the - * given DOM element. - * - * - * @param expressionOrAst - * @param element - */ - run, - /** - * **experimential** This API is experimential and might be removed in the future - * without notice - * - * Component which executes and renders the given expression in a div element. - * The expression is re-executed on updating the props. - * - * This is a React bridge of the `run` method - * @param props - */ - ExpressionRenderer: createRenderer(run), - }; - } - - public stop() { - // nothing to do here yet - } -} - -/** @public */ -export type ExpressionsSetup = ReturnType; diff --git a/src/legacy/core_plugins/data/public/expressions/index.ts b/src/legacy/core_plugins/data/public/expressions/index.ts deleted file mode 100644 index fceefce44f81f..0000000000000 --- a/src/legacy/core_plugins/data/public/expressions/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. - */ - -export { ExpressionsService, ExpressionsSetup } from './expressions_service'; -export { ExpressionRenderer, ExpressionRendererProps } from './expression_renderer'; -export { ExpressionRunner } from './expression_runner'; diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss index 7fbe295b95571..f4586c7c0fbc3 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_group.scss @@ -25,6 +25,15 @@ transition: height $euiAnimSpeedNormal $euiAnimSlightResistance; } +.globalFilterGroup__filterFlexItem { + overflow: hidden; + padding-bottom: 2px; // Allow the shadows of the pills to show +} + +.globalFilterBar__flexItem { + max-width: calc(100% - #{$euiSizeXS}); // Width minus margin around each flex itm +} + @include euiBreakpoint('xs', 's') { .globalFilterGroup__wrapper-isVisible { // EUI Flexbox adds too much margin between responded items, this just moves it up diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss index f128d6db189e6..caf3b0b796b9e 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/_global_filter_item.scss @@ -40,9 +40,16 @@ left: 0; width: $euiSizeXS; background-color: $euiColorVis0; + border-top-left-radius: $euiBorderRadius / 2; + border-bottom-left-radius: $euiBorderRadius / 2; } } .globalFilterItem__editorForm { padding: $euiSizeM; } + +.globalFilterItem__popover, +.globalFilterItem__popoverAnchor { + display: block; +} diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx index ca2b26cc3202d..4ca1d581aef7d 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_bar.tsx @@ -56,6 +56,9 @@ class FilterBarUI extends Component { }; public render() { + if (!this.props.uiSettings) { + return null; + } const classes = classNames('globalFilterBar', this.props.className); return ( @@ -77,7 +80,7 @@ class FilterBarUI extends Component { /> - + { private renderItems() { return this.props.filters.map((filter, i) => ( - + ({ - kfetch: () => {}, -})); - -jest.mock( - 'ui/notify', - () => ({ - toastNotifications: { - addWarning: () => {}, - }, - }), - { virtual: true } -); - -const { mockFields, mockIndexPattern } = fixtures; +jest.mock('ui/new_platform'); + const mockedFields = mockFields as Field[]; const mockedIndexPattern = mockIndexPattern as IndexPattern; diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts index 3b7c8c1feb44a..f0628f03c173e 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/lib/filter_editor_utils.ts @@ -32,8 +32,8 @@ import { RangeFilter, } from '@kbn/es-query'; import { omit } from 'lodash'; -import Ipv4Address from 'ui/utils/ipv4_address'; -import { Field, IndexPattern, utils as indexPatternUtils } from '../../../../index_patterns'; +import { Ipv4Address } from '../../../../../../../../plugins/kibana_utils/public'; +import { Field, IndexPattern, isFilterable } from '../../../../index_patterns'; import { FILTER_OPERATORS, Operator } from './filter_operators'; export function getIndexPatternFromFilter( @@ -58,7 +58,7 @@ export function getQueryDslFromFilter(filter: Filter) { } export function getFilterableFields(indexPattern: IndexPattern) { - return indexPattern.fields.filter(indexPatternUtils.isFilterable); + return indexPattern.fields.filter(isFilterable); } export function getOperatorOptions(field: Field) { diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx index f33ce3d7486fc..0696bacc568b5 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_editor/phrase_value_input.tsx @@ -60,7 +60,9 @@ class PhraseValueInputUI extends PhraseSuggestor { private renderWithSuggestions() { const { suggestions } = this.state; const { value, intl, onChange } = this.props; - const options = value ? uniq([value, ...suggestions]) : suggestions; + // there are cases when the value is a number, this would cause an exception + const valueAsStr = String(value); + const options = value ? uniq([valueAsStr, ...suggestions]) : suggestions; return ( { })} options={options} getLabel={option => option} - selectedOptions={value ? [value] : []} + selectedOptions={value ? [valueAsStr] : []} onChange={([newValue = '']) => onChange(newValue)} onSearchChange={this.onSearchChange} singleSelection={{ asPlainText: true }} diff --git a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx index ee8d660e44f55..17c557a9ff3d3 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx +++ b/src/legacy/core_plugins/data/public/filter/filter_bar/filter_item.tsx @@ -181,6 +181,8 @@ class FilterItemUI extends Component { return ( ; + +const createSetupContractMock = () => { + const setupContract: jest.Mocked = { + filterManager: jest.fn() as any, + }; + + return setupContract; +}; + +const createMock = () => { + const mocked: jest.Mocked = { + setup: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + }; + + mocked.setup.mockReturnValue(createSetupContractMock()); + return mocked; +}; + +export const filterServiceMock = { + create: createMock, + createSetupContract: createSetupContractMock, + createStartContract: createSetupContractMock, +}; diff --git a/src/legacy/core_plugins/data/public/filter/filter_service.ts b/src/legacy/core_plugins/data/public/filter/filter_service.ts index f56534490afc4..063b69c175b20 100644 --- a/src/legacy/core_plugins/data/public/filter/filter_service.ts +++ b/src/legacy/core_plugins/data/public/filter/filter_service.ts @@ -20,8 +20,9 @@ import { UiSettingsClientContract } from 'src/core/public'; import { IndexPatterns } from '../index_patterns'; import { FilterManager } from './filter_manager'; + /** - * FilterSearch Service + * Filter Service * @internal */ @@ -37,6 +38,10 @@ export class FilterService { }; } + public start() { + // nothing to do here yet + } + public stop() { // nothing to do here yet } diff --git a/src/legacy/core_plugins/data/public/index.scss b/src/legacy/core_plugins/data/public/index.scss index 993e52665defa..14274d27c13ee 100644 --- a/src/legacy/core_plugins/data/public/index.scss +++ b/src/legacy/core_plugins/data/public/index.scss @@ -4,3 +4,4 @@ @import './filter/filter_bar/index'; +@import './search/search_bar/index'; diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts index 4f9f3b323fbb5..8837c125e2ab2 100644 --- a/src/legacy/core_plugins/data/public/index.ts +++ b/src/legacy/core_plugins/data/public/index.ts @@ -28,27 +28,41 @@ export function plugin() { /** @public types */ export type DataSetup = DataSetup; -export { ExpressionRenderer, ExpressionRendererProps, ExpressionRunner } from './expressions'; -/** @public types */ -export { IndexPattern, IndexPatterns, StaticIndexPattern, Field } from './index_patterns'; -export { Query, QueryBar, QueryBarInput } from './query'; export { FilterBar, ApplyFiltersPopover } from './filter'; -export { SearchBar, SearchBarProps } from './search'; +export { + Field, + FieldType, + IndexPattern, + IndexPatterns, + StaticIndexPattern, +} from './index_patterns'; +export { Query, QueryBar, QueryBarInput } from './query'; +export { SearchBar, SearchBarProps, SavedQueryAttributes, SavedQuery } from './search'; + +/** @public static code */ +export * from '../common'; export { FilterManager, FilterStateManager, uniqFilters, onlyDisabledFiltersChanged, } from './filter/filter_manager'; - -/** @public static code */ -export { dateHistogramInterval } from '../common/date_histogram_interval'; -/** @public static code */ export { - isValidEsInterval, - InvalidEsCalendarIntervalError, - InvalidEsIntervalFormatError, - parseEsInterval, - ParsedInterval, -} from '../common/parse_es_interval'; + CONTAINS_SPACES, + getFromSavedObject, + getRoutes, + isFilterable, + IndexPatternSelect, + IndexPatternsProvider, // LEGACY + validateIndexPattern, + ILLEGAL_CHARACTERS, + INDEX_PATTERN_ILLEGAL_CHARACTERS, + INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE, + IndexPatternAlreadyExists, + IndexPatternMissingIndices, + NoDefaultIndexPattern, + NoDefinedIndexPatterns, + mockFields, + mockIndexPattern, +} from './index_patterns'; diff --git a/src/legacy/core_plugins/data/public/index_patterns/components/index.ts b/src/legacy/core_plugins/data/public/index_patterns/components/index.ts new file mode 100644 index 0000000000000..30dcb43557507 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/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 * from './index_pattern_select'; diff --git a/src/legacy/ui/public/index_patterns/components/index_pattern_select.tsx b/src/legacy/core_plugins/data/public/index_patterns/components/index_pattern_select.tsx similarity index 78% rename from src/legacy/ui/public/index_patterns/components/index_pattern_select.tsx rename to src/legacy/core_plugins/data/public/index_patterns/components/index_pattern_select.tsx index e8e5f8c08278f..c6f3a6e35bc43 100644 --- a/src/legacy/ui/public/index_patterns/components/index_pattern_select.tsx +++ b/src/legacy/core_plugins/data/public/index_patterns/components/index_pattern_select.tsx @@ -19,9 +19,9 @@ import _ from 'lodash'; import React, { Component } from 'react'; -import chrome from 'ui/chrome'; import { EuiComboBox } from '@elastic/eui'; +import { SavedObjectsClientContract, SimpleSavedObject } from '../../../../../../core/public'; interface IndexPatternSelectProps { onChange: (opt: any) => void; @@ -29,6 +29,7 @@ interface IndexPatternSelectProps { placeholder: string; fieldTypes: string[]; onNoIndexPatterns: () => void; + savedObjectsClient: SavedObjectsClientContract; } interface IndexPatternSelectState { @@ -38,8 +39,12 @@ interface IndexPatternSelectState { searchValue: string | undefined; } -const getIndexPatterns = async (search: string, fields: string[]) => { - const resp = await chrome.getSavedObjectsClient().find({ +const getIndexPatterns = async ( + client: SavedObjectsClientContract, + search: string, + fields: string[] +) => { + const resp = await client.find({ type: 'index-pattern', fields, search: `${search}*`, @@ -49,14 +54,24 @@ const getIndexPatterns = async (search: string, fields: string[]) => { return resp.savedObjects; }; -const getIndexPatternTitle = async (indexPatternId: string) => { - const savedObject = await chrome.getSavedObjectsClient().get('index-pattern', indexPatternId); +const getIndexPatternTitle = async ( + client: SavedObjectsClientContract, + indexPatternId: string +): Promise> => { + const savedObject = (await client.get('index-pattern', indexPatternId)) as SimpleSavedObject; if (savedObject.error) { throw new Error(`Unable to get index-pattern title: ${savedObject.error.message}`); } return savedObject.attributes.title; }; +// 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 { private isMounted: boolean = false; state: IndexPatternSelectState; @@ -99,7 +114,7 @@ export class IndexPatternSelect extends Component { let indexPatternTitle; try { - indexPatternTitle = await getIndexPatternTitle(indexPatternId); + indexPatternTitle = await getIndexPatternTitle(this.props.savedObjectsClient, indexPatternId); } catch (err) { // index pattern no longer exists return; @@ -118,16 +133,16 @@ export class IndexPatternSelect extends Component { }; debouncedFetch = _.debounce(async (searchValue: string) => { - const { fieldTypes, onNoIndexPatterns } = this.props; + const { fieldTypes, onNoIndexPatterns, savedObjectsClient } = this.props; const savedObjectFields = ['title']; if (fieldTypes) { savedObjectFields.push('fields'); } - let savedObjects = await getIndexPatterns(searchValue, savedObjectFields); + let savedObjects = await getIndexPatterns(savedObjectsClient, searchValue, savedObjectFields); if (fieldTypes) { - savedObjects = savedObjects.filter(savedObject => { + savedObjects = savedObjects.filter((savedObject: SimpleSavedObject) => { try { const indexPatternFields = JSON.parse(savedObject.attributes.fields as any); return indexPatternFields.some((field: any) => { @@ -147,7 +162,7 @@ export class IndexPatternSelect extends Component { // We need this check to handle the case where search results come back in a different // order than they were sent out. Only load results for the most recent search. if (searchValue === this.state.searchValue) { - const options = savedObjects.map(indexPatternSavedObject => { + const options = savedObjects.map((indexPatternSavedObject: SimpleSavedObject) => { return { label: indexPatternSavedObject.attributes.title, value: indexPatternSavedObject.id, @@ -185,6 +200,7 @@ export class IndexPatternSelect extends Component { indexPatternId, // eslint-disable-line no-unused-vars placeholder, onNoIndexPatterns, // eslint-disable-line no-unused-vars + savedObjectsClient, // eslint-disable-line no-unused-vars ...rest } = this.props; diff --git a/src/legacy/core_plugins/data/public/index_patterns/errors.ts b/src/legacy/core_plugins/data/public/index_patterns/errors.ts new file mode 100644 index 0000000000000..df7f26ad6673d --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/errors.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. + */ + +/* eslint-disable */ + +// @ts-ignore +import { KbnError } from 'ui/errors'; + +/** + * when a mapping already exists for a field the user is attempting to add + * @param {String} name - the field name + */ +export class IndexPatternAlreadyExists extends KbnError { + constructor(name: string) { + super(`An index pattern of "${name}" already exists`, IndexPatternAlreadyExists); + } +} + +/** + * Tried to call a method that relies on SearchSource having an indexPattern assigned + */ +export class IndexPatternMissingIndices extends KbnError { + constructor(message: string) { + const defaultMessage = "IndexPattern's configured pattern does not match any indices"; + + super( + message && message.length ? `No matching indices found: ${message}` : defaultMessage, + IndexPatternMissingIndices + ); + } +} + +/** + * Tried to call a method that relies on SearchSource having an indexPattern assigned + */ +export class NoDefinedIndexPatterns extends KbnError { + constructor() { + super('Define at least one index pattern to continue', NoDefinedIndexPatterns); + } +} + +/** + * Tried to load a route besides management/kibana/index but you don't have a default index pattern! + */ +export class NoDefaultIndexPattern extends KbnError { + constructor() { + super('Please specify a default index pattern', NoDefaultIndexPattern); + } +} diff --git a/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts new file mode 100644 index 0000000000000..cd077fc676611 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/fields/field.ts @@ -0,0 +1,177 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +import { fieldFormats } from 'ui/registry/field_formats'; +import { toastNotifications } from 'ui/notify'; +import { i18n } from '@kbn/i18n'; +// @ts-ignore +import { ObjDefine } from './obj_define'; +// @ts-ignore +import { getKbnFieldType } from '../../../../../utils/kbn_field_types'; +// @ts-ignore +import { FieldFormat } from '../../../../../ui/field_formats/field_format'; +// @ts-ignore +import { shortenDottedString } from '../../../../../core_plugins/kibana/common/utils/shorten_dotted_string'; +import { IndexPattern } from '../index_patterns'; + +export type FieldSpec = Record; +export interface FieldType { + name: string; + type: string; + script?: string; + lang?: string; + count?: number; + // esTypes might be undefined on old index patterns that have not been refreshed since we added + // this prop. It is also undefined on scripted fields. + esTypes?: string[]; + aggregatable?: boolean; + filterable?: boolean; + searchable?: boolean; + sortable?: boolean; + visualizable?: boolean; + readFromDocValues?: boolean; + scripted?: boolean; + parent?: string; + subType?: string; + displayName?: string; + format?: any; +} + +export class Field implements FieldType { + name: string; + type: string; + script?: string; + lang?: string; + count?: number; + // esTypes might be undefined on old index patterns that have not been refreshed since we added + // this prop. It is also undefined on scripted fields. + esTypes?: string[]; + aggregatable?: boolean; + filterable?: boolean; + searchable?: boolean; + sortable?: boolean; + visualizable?: boolean; + scripted?: boolean; + parent?: string; + subType?: string; + displayName?: string; + format: any; + routes: Record = { + edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}', + }; + $$spec: FieldSpec; + + constructor( + indexPattern: IndexPattern, + spec: FieldSpec | Field, + shortDotsEnable: boolean = false + ) { + // unwrap old instances of Field + if (spec instanceof Field) spec = spec.$$spec; + + // construct this object using ObjDefine class, which + // extends the Field.prototype but gets it's properties + // defined using the logic below + const obj = new ObjDefine(spec, Field.prototype); + + if (spec.name === '_source') { + spec.type = '_source'; + } + + // find the type for this field, fallback to unknown type + let type = getKbnFieldType(spec.type); + if (spec.type && !type) { + const title = i18n.translate('data.indexPatterns.unknownFieldHeader', { + values: { type: spec.type }, + defaultMessage: 'Unknown field type {type}', + }); + const text = i18n.translate('data.indexPatterns.unknownFieldErrorMessage', { + values: { name: spec.name, title: indexPattern.title }, + defaultMessage: 'Field {name} in indexPattern {title} is using an unknown field type.', + }); + + toastNotifications.addDanger({ + title, + text, + }); + } + + if (!type) type = getKbnFieldType('unknown'); + + let format = spec.format; + if (!format || !(format instanceof FieldFormat)) { + format = + indexPattern.fieldFormatMap[spec.name] || + fieldFormats.getDefaultInstance(spec.type, spec.esTypes); + } + + const indexed = !!spec.indexed; + const scripted = !!spec.scripted; + const searchable = !!spec.searchable || scripted; + const aggregatable = !!spec.aggregatable || scripted; + const readFromDocValues = !!spec.readFromDocValues && !scripted; + const sortable = spec.name === '_score' || ((indexed || aggregatable) && type.sortable); + const filterable = + spec.name === '_id' || scripted || ((indexed || searchable) && type.filterable); + const visualizable = aggregatable; + + this.name = ''; + obj.fact('name'); + this.type = ''; + obj.fact('type'); + obj.fact('esTypes'); + obj.writ('count', spec.count || 0); + + // scripted objs + obj.fact('scripted', scripted); + obj.writ('script', scripted ? spec.script : null); + obj.writ('lang', scripted ? spec.lang || 'painless' : null); + + // stats + obj.fact('searchable', searchable); + obj.fact('aggregatable', aggregatable); + obj.fact('readFromDocValues', readFromDocValues); + + // usage flags, read-only and won't be saved + obj.comp('format', format); + obj.comp('sortable', sortable); + obj.comp('filterable', filterable); + obj.comp('visualizable', visualizable); + + // computed values + obj.comp('indexPattern', indexPattern); + obj.comp('displayName', shortDotsEnable ? shortenDottedString(spec.name) : spec.name); + this.$$spec = spec; + obj.comp('$$spec', spec); + + // conflict info + obj.writ('conflictDescriptions'); + + // multi info + obj.fact('parent'); + obj.fact('subType'); + + return obj.create(); + } +} + +Field.prototype.routes = { + edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}', +}; diff --git a/src/legacy/core_plugins/data/public/index_patterns/fields/field_list.ts b/src/legacy/core_plugins/data/public/index_patterns/fields/field_list.ts new file mode 100644 index 0000000000000..d167714f76b16 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/fields/field_list.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 { IndexedArray } from 'ui/indexed_array'; +import { IndexPattern } from '../index_patterns'; +import { Field, FieldSpec } from './field'; + +export class FieldList extends IndexedArray { + constructor(indexPattern: IndexPattern, specs: FieldSpec[], shortDotsEnable = false) { + super({ + index: ['name'], + group: ['type'], + initialSet: specs.map(function(field) { + return new Field(indexPattern, field, shortDotsEnable); + }), + }); + } +} diff --git a/src/legacy/core_plugins/data/public/index_patterns/fields/index.ts b/src/legacy/core_plugins/data/public/index_patterns/fields/index.ts new file mode 100644 index 0000000000000..1644e23a163a6 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/fields/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 './field_list'; +export * from './field'; diff --git a/src/legacy/ui/public/utils/obj_define.js b/src/legacy/core_plugins/data/public/index_patterns/fields/obj_define.js similarity index 100% rename from src/legacy/ui/public/utils/obj_define.js rename to src/legacy/core_plugins/data/public/index_patterns/fields/obj_define.js diff --git a/src/legacy/core_plugins/data/public/index_patterns/fields/obj_define.test.js b/src/legacy/core_plugins/data/public/index_patterns/fields/obj_define.test.js new file mode 100644 index 0000000000000..e140940b0fc17 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/fields/obj_define.test.js @@ -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 expect from '@kbn/expect'; +import { ObjDefine } from './obj_define'; + +describe('ObjDefine Utility', function () { + + function flatten(obj) { + return JSON.parse(JSON.stringify(obj)); + } + + describe('#writ', function () { + it('creates writeable properties', function () { + const def = new ObjDefine(); + def.writ('name', 'foo'); + + const obj = def.create(); + expect(obj).to.have.property('name', 'foo'); + + obj.name = 'bar'; + expect(obj).to.have.property('name', 'bar'); + }); + + it('exports the property to JSON', function () { + const def = new ObjDefine(); + def.writ('name', 'foo'); + expect(flatten(def.create())).to.have.property('name', 'foo'); + }); + + it('does not export property to JSON it it\'s undefined or null', function () { + const def = new ObjDefine(); + def.writ('name'); + expect(flatten(def.create())).to.not.have.property('name'); + + def.writ('name', null); + expect(flatten(def.create())).to.not.have.property('name'); + }); + + it('switched to exporting if a value is written', function () { + const def = new ObjDefine(); + def.writ('name'); + + const obj = def.create(); + expect(flatten(obj)).to.not.have.property('name'); + + obj.name = null; + expect(flatten(obj)).to.not.have.property('name'); + + obj.name = 'foo'; + expect(flatten(obj)).to.have.property('name', 'foo'); + }); + + it('setting a writ value to null prevents it from exporting', function () { + const def = new ObjDefine(); + def.writ('name', 'foo'); + + const obj = def.create(); + expect(flatten(obj)).to.have.property('name', 'foo'); + + obj.name = null; + expect(flatten(obj)).to.not.have.property('name'); + }); + + }); + + describe('#fact', function () { + it('creates an immutable field', function () { + const def = new ObjDefine(); + const val = 'foo'; + const notval = 'bar'; + def.fact('name', val); + const obj = def.create(); + + + obj.name = notval; // UPDATE SHOULD BE IGNORED + expect(obj).to.have.property('name', val); + }); + + it('exports the fact to JSON', function () { + const def = new ObjDefine(); + def.fact('name', 'foo'); + expect(flatten(def.create())).to.have.property('name', 'foo'); + }); + }); + + describe('#comp', function () { + it('creates an immutable field', function () { + const def = new ObjDefine(); + const val = 'foo'; + const notval = 'bar'; + def.comp('name', val); + const obj = def.create(); + + expect(function () { + 'use strict'; // eslint-disable-line strict + + obj.name = notval; + }).to.throwException(); + }); + + it('does not export the computed value to JSON', function () { + const def = new ObjDefine(); + def.comp('name', 'foo'); + expect(flatten(def.create())).to.not.have.property('name'); + }); + }); + + + describe('#create', function () { + it('creates object that inherits from the prototype', function () { + function SomeClass() {} + + const def = new ObjDefine(null, SomeClass.prototype); + const obj = def.create(); + + expect(obj).to.be.a(SomeClass); + }); + + it('uses the defaults for property values', function () { + const def = new ObjDefine({ name: 'bar' }); + def.fact('name'); + + const obj = def.create(); + + expect(obj).to.have.property('name', 'bar'); + }); + + it('ignores default values that are not defined properties', function () { + const def = new ObjDefine({ name: 'foo', name2: 'bar' }); + const obj = def.create(); + + expect(obj).to.not.have.property('name'); + expect(obj).to.not.have.property('name2'); + }); + }); + +}); diff --git a/src/legacy/core_plugins/data/public/index_patterns/index.ts b/src/legacy/core_plugins/data/public/index_patterns/index.ts index ba211850d52f8..496c4ba7b5b6f 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index.ts @@ -17,15 +17,4 @@ * under the License. */ -export { - IndexPatternsService, - IndexPatterns, - fixtures, - utils, - // types - IndexPatternsSetup, - IndexPattern, - StaticIndexPattern, - Field, - FieldType, -} from './index_patterns_service'; +export * from './index_patterns_service'; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/_fields_fetcher.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/_fields_fetcher.ts new file mode 100644 index 0000000000000..c61df91cb8d1b --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/_fields_fetcher.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 { IndexPattern } from './index_pattern'; +import { GetFieldsOptions, IndexPatternsApiClient } from './index_patterns_api_client'; + +/** @internal */ +export const createFieldsFetcher = ( + indexPattern: IndexPattern, + apiClient: IndexPatternsApiClient, + 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/legacy/ui/public/index_patterns/_pattern_cache.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/_pattern_cache.ts similarity index 96% rename from src/legacy/ui/public/index_patterns/_pattern_cache.ts rename to src/legacy/core_plugins/data/public/index_patterns/index_patterns/_pattern_cache.ts index 56c19f625f10a..adc34e34f58e5 100644 --- a/src/legacy/ui/public/index_patterns/_pattern_cache.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/_pattern_cache.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IndexPattern } from './index'; +import { IndexPattern } from './index_pattern'; export interface PatternCache { get: (id: string) => IndexPattern; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/flatten_hit.js b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/flatten_hit.js new file mode 100644 index 0000000000000..b9d25dc0ccb41 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/flatten_hit.js @@ -0,0 +1,113 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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'; + +// Takes a hit, merges it with any stored/scripted fields, and with the metaFields +// returns a flattened version + +function flattenHit(indexPattern, hit, deep) { + const flat = {}; + + // recursively merge _source + const fields = indexPattern.fields.byName; + (function flatten(obj, keyPrefix) { + keyPrefix = keyPrefix ? keyPrefix + '.' : ''; + _.forOwn(obj, function (val, key) { + key = keyPrefix + key; + + if (deep) { + const isNestedField = fields[key] && fields[key].type === 'nested'; + const isArrayOfObjects = Array.isArray(val) && _.isPlainObject(_.first(val)); + if (isArrayOfObjects && !isNestedField) { + _.each(val, v => flatten(v, key)); + return; + } + } else if (flat[key] !== void 0) { + return; + } + + const hasValidMapping = fields[key] && fields[key].type !== 'conflict'; + const isValue = !_.isPlainObject(val); + + if (hasValidMapping || isValue) { + if (!flat[key]) { + flat[key] = val; + } else if (Array.isArray(flat[key])) { + flat[key].push(val); + } else { + flat[key] = [ flat[key], val ]; + } + return; + } + + flatten(val, key); + }); + }(hit._source)); + + return flat; +} + +function decorateFlattenedWrapper(hit, metaFields) { + return function (flattened) { + // assign the meta fields + _.each(metaFields, function (meta) { + if (meta === '_source') return; + flattened[meta] = hit[meta]; + }); + + // unwrap computed fields + _.forOwn(hit.fields, function (val, key) { + if (key[0] === '_' && !_.contains(metaFields, key)) return; + flattened[key] = Array.isArray(val) && val.length === 1 ? val[0] : val; + }); + + return flattened; + }; +} + +/** + * This is wrapped by `createFlattenHitWrapper` in order to provide a single cache to be + * shared across all uses of this function. It is only exported here for use in mocks. + * + * @internal + */ +export function flattenHitWrapper(indexPattern, metaFields = {}, cache = new WeakMap()) { + return function cachedFlatten(hit, deep = false) { + const decorateFlattened = decorateFlattenedWrapper(hit, metaFields); + const cached = cache.get(hit); + const flattened = cached || flattenHit(indexPattern, hit, deep); + if (!cached) { + cache.set(hit, { ...flattened }); + } + return decorateFlattened(flattened); + }; +} + +/** + * This wraps `flattenHitWrapper` so one single cache can be provided for all uses of that + * function. The returned value of this function is what is included in the index patterns + * setup contract. + * + * @public + */ +export function createFlattenHitWrapper() { + const cache = new WeakMap(); + return _.partial(flattenHitWrapper, _, _, cache); +} diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/format_hit.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/format_hit.ts new file mode 100644 index 0000000000000..39101ef36ca8d --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/format_hit.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 _ from 'lodash'; +import { IndexPattern } from './index_pattern'; + +const formattedCache = new WeakMap(); +const partialFormattedCache = new WeakMap(); + +// Takes a hit, merges it with any stored/scripted fields, and with the metaFields +// returns a formatted version +export function formatHitProvider(indexPattern: IndexPattern, defaultFormat: any) { + function convert(hit: Record, val: any, fieldName: string, type: string = 'html') { + const field = indexPattern.fields.byName[fieldName]; + if (!field) return defaultFormat.convert(val, type); + const parsedUrl = { + origin: window.location.origin, + pathname: window.location.pathname, + }; + return field.format.getConverterFor(type)(val, field, hit, parsedUrl); + } + + function formatHit(hit: Record, type: string = 'html') { + if (type === 'text') { + // formatHit of type text is for react components to get rid of + // since it's currently just used at the discover's doc view table, caching is not necessary + const flattened = indexPattern.flattenHit(hit); + const result: Record = {}; + for (const [key, value] of Object.entries(flattened)) { + result[key] = convert(hit, value, key, type); + } + return result; + } + + const cached = formattedCache.get(hit); + if (cached) { + return cached; + } + + // use and update the partial cache, but don't rewrite it. + // _source is stored in partialFormattedCache but not formattedCache + const partials = partialFormattedCache.get(hit) || {}; + partialFormattedCache.set(hit, partials); + + const cache: Record = {}; + formattedCache.set(hit, cache); + + _.forOwn(indexPattern.flattenHit(hit), function(val: any, fieldName?: string) { + // sync the formatted and partial cache + if (!fieldName) { + return; + } + const formatted = + partials[fieldName] == null ? convert(hit, val, fieldName) : partials[fieldName]; + cache[fieldName] = partials[fieldName] = formatted; + }); + + return cache; + } + + formatHit.formatField = function(hit: Record, fieldName: string) { + let partials = partialFormattedCache.get(hit); + if (partials && partials[fieldName] != null) { + return partials[fieldName]; + } + + if (!partials) { + partials = {}; + partialFormattedCache.set(hit, partials); + } + + const val = fieldName === '_source' ? hit._source : indexPattern.flattenHit(hit)[fieldName]; + return convert(hit, val, fieldName); + }; + + return formatHit; +} diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index.ts new file mode 100644 index 0000000000000..31ff03d51f97a --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/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-ignore +export * from './flatten_hit'; +export * from './format_hit'; +export * from './index_pattern'; +export * from './index_patterns'; +export * from './index_patterns_api_client'; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts new file mode 100644 index 0000000000000..4a401e0b5e44f --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts @@ -0,0 +1,413 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { defaults, pluck, last, get } from 'lodash'; +import { IndexedArray } from 'ui/indexed_array'; +import { IndexPattern } from './index_pattern'; + +// @ts-ignore +import { DuplicateField } from 'ui/errors'; +// @ts-ignore +import mockLogStashFields from '../../../../../../fixtures/logstash_fields'; +// @ts-ignore + +import { stubbedSavedObjectIndexPattern } from '../../../../../../fixtures/stubbed_saved_object_index_pattern'; +import { Field } from '../index_patterns_service'; + +jest.mock('ui/registry/field_formats', () => ({ + fieldFormats: { + getDefaultInstance: jest.fn(), + }, +})); + +jest.mock('ui/utils/mapping_setup', () => ({ + expandShorthand: jest.fn().mockImplementation(() => ({ + id: true, + title: true, + fieldFormatMap: { + _deserialize: jest.fn().mockImplementation(() => []), + }, + })), +})); + +jest.mock('ui/notify', () => ({ + toastNotifications: { + addDanger: jest.fn(), + addError: jest.fn(), + }, +})); + +jest.mock('ui/saved_objects', () => { + return { + findObjectByTitle: jest.fn(), + }; +}); + +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(), +}; + +const config = { + get: 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, + (cfg: any) => config.get(cfg), + savedObjectsClient as any, + apiClient, + patternCache + ); + + 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; + }); + }); + + 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'); + expect(indexPattern).toHaveProperty('removeScriptedField'); + expect(indexPattern).toHaveProperty('toString'); + expect(indexPattern).toHaveProperty('toJSON'); + expect(indexPattern).toHaveProperty('save'); + + // properties + expect(indexPattern).toHaveProperty('fields'); + }); + }); + + describe('init', () => { + test('should append the found fields', () => { + expect(savedObjectsClient.get).toHaveBeenCalled(); + expect(indexPattern.fields).toHaveLength(mockLogStashFields().length); + expect(indexPattern.fields).toBeInstanceOf(IndexedArray); + }); + }); + + describe('fields', () => { + test('should have expected properties on fields', function() { + expect(indexPattern.fields[0]).toHaveProperty('displayName'); + expect(indexPattern.fields[0]).toHaveProperty('filterable'); + expect(indexPattern.fields[0]).toHaveProperty('format'); + expect(indexPattern.fields[0]).toHaveProperty('sortable'); + expect(indexPattern.fields[0]).toHaveProperty('scripted'); + }); + }); + + describe('getScriptedFields', () => { + test('should return all scripted fields', () => { + const scriptedNames = mockLogStashFields() + .filter((item: Field) => item.scripted === true) + .map((item: Field) => item.name); + const respNames = pluck(indexPattern.getScriptedFields(), 'name'); + + expect(respNames).toEqual(scriptedNames); + }); + }); + + describe('getComputedFields', () => { + test('should be a function', () => { + expect(indexPattern.getComputedFields).toBeInstanceOf(Function); + }); + + test('should request all stored fields', () => { + expect(indexPattern.getComputedFields().storedFields).toContain('*'); + }); + + test('should request date fields as docvalue_fields', () => { + const { docvalueFields } = indexPattern.getComputedFields(); + const docValueFieldNames = docvalueFields.map(field => field.field); + + expect(Object.keys(docValueFieldNames).length).toBe(3); + expect(docValueFieldNames).toContain('@timestamp'); + expect(docValueFieldNames).toContain('time'); + expect(docValueFieldNames).toContain('utc_time'); + }); + + test('should request date field doc values in date_time format', () => { + const { docvalueFields } = indexPattern.getComputedFields(); + const timestampField = docvalueFields.find(field => field.field === '@timestamp'); + + expect(timestampField).toHaveProperty('format', 'date_time'); + }); + + test('should not request scripted date fields as docvalue_fields', () => { + const { docvalueFields } = indexPattern.getComputedFields(); + + expect(docvalueFields).not.toContain('script date'); + }); + }); + + describe('getNonScriptedFields', () => { + test('should return all non-scripted fields', () => { + const notScriptedNames = mockLogStashFields() + .filter((item: Field) => item.scripted === false) + .map((item: Field) => item.name); + const respNames = pluck(indexPattern.getNonScriptedFields(), 'name'); + + expect(respNames).toEqual(notScriptedNames); + }); + }); + + 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: Field) => f.scripted) + .map((f: Field) => 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 + const scriptedField = { + name: 'new scripted field', + script: 'false', + type: 'boolean', + }; + + await indexPattern.addScriptedField( + scriptedField.name, + scriptedField.script, + scriptedField.type, + 'lang' + ); + + const scriptedFields = indexPattern.getScriptedFields(); + // expect(saveSpy.callCount).to.equal(1); + expect(scriptedFields).toHaveLength(oldCount + 1); + expect(indexPattern.fields.byName[scriptedField.name].name).toEqual(scriptedField.name); + }); + + 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.byName[scriptedField.name]).toEqual(undefined); + }); + + test('should not allow duplicate names', async () => { + const scriptedFields = indexPattern.getScriptedFields(); + const scriptedField = last(scriptedFields); + expect.assertions(1); + try { + await indexPattern.addScriptedField(scriptedField.name, "'new script'", 'string', 'lang'); + } catch (e) { + expect(e).toBeInstanceOf(DuplicateField); + } + }); + }); + + 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); + }); + }); + }); + + test('should handle version conflicts', async () => { + setDocsourcePayload(null, { + _id: 'foo', + _version: 'foo', + attributes: { + title: 'something', + }, + }); + // Create a normal index pattern + const pattern = new IndexPattern( + 'foo', + (cfg: any) => config.get(cfg), + savedObjectsClient as any, + apiClient, + patternCache + ); + await pattern.init(); + + expect(get(pattern, 'version')).toBe('fooa'); + + // Create the same one - we're going to handle concurrency + const samePattern = new IndexPattern( + 'foo', + (cfg: any) => config.get(cfg), + savedObjectsClient as any, + apiClient, + patternCache + ); + await samePattern.init(); + + expect(get(samePattern, 'version')).toBe('fooaa'); + + // This will conflict because samePattern did a save (from refreshFields) + // but the resave should work fine + pattern.title = 'foo2'; + await pattern.save(); + + // This should not be able to recover + samePattern.title = 'foo3'; + + let result; + try { + await samePattern.save(); + } catch (err) { + result = err; + } + + expect(result.res.status).toBe(409); + }); +}); diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts new file mode 100644 index 0000000000000..6a4cf6fe45390 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -0,0 +1,529 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _, { each, reject } from 'lodash'; +import { i18n } from '@kbn/i18n'; +// @ts-ignore +import { SavedObjectNotFound, DuplicateField } from 'ui/errors'; +// @ts-ignore +import { fieldFormats } from 'ui/registry/field_formats'; +// @ts-ignore +import { expandShorthand } from 'ui/utils/mapping_setup'; +import { toastNotifications } from 'ui/notify'; +import { findObjectByTitle } from 'ui/saved_objects'; +import { SavedObjectsClientContract } from 'src/core/public'; + +import { IndexPatternMissingIndices } from '../errors'; +import { Field, FieldList, FieldType } from '../fields'; +import { createFieldsFetcher } from './_fields_fetcher'; +import { getRoutes } from '../utils'; +import { formatHitProvider } from './format_hit'; +// @ts-ignore +import { flattenHitWrapper } from './flatten_hit'; +import { IndexPatternsApiClient } from './index_patterns_api_client'; + +const MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS = 3; +const type = 'index-pattern'; + +interface FieldMappingSpec { + _serialize: (mapping: any) => string; + _deserialize: (mapping: string) => any; +} + +interface MappingObject { + [key: string]: FieldMappingSpec; +} + +export interface StaticIndexPattern { + fields: FieldType[]; + title: string; + id?: string; + type?: string; + timeFieldName?: string; +} + +export class IndexPattern implements StaticIndexPattern { + [key: string]: any; + + public id?: string; + public title: string = ''; + public type?: string; + public fieldFormatMap: any; + public typeMeta: any; + public fields: FieldList; + public timeFieldName: string | undefined; + public formatHit: any; + public formatField: any; + public flattenHit: any; + public metaFields: string[]; + + private version: string | undefined; + private savedObjectsClient: SavedObjectsClientContract; + private patternCache: any; + private getConfig: any; + private sourceFilters?: []; + private originalBody: { [key: string]: any } = {}; + private fieldsFetcher: any; + private shortDotsEnable: boolean = false; + + private mapping: MappingObject = expandShorthand({ + title: 'text', + timeFieldName: 'keyword', + intervalName: 'keyword', + fields: 'json', + sourceFilters: 'json', + fieldFormatMap: { + type: '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: 'keyword', + typeMeta: 'json', + }); + + constructor( + id: string | undefined, + getConfig: any, + savedObjectsClient: SavedObjectsClientContract, + apiClient: IndexPatternsApiClient, + patternCache: any + ) { + this.id = id; + this.savedObjectsClient = savedObjectsClient; + this.patternCache = patternCache; + // instead of storing config we rather store the getter only as np uiSettingsClient has circular references + // which cause problems when being consumed from angular + this.getConfig = getConfig; + + this.shortDotsEnable = this.getConfig('shortDots:enable'); + this.metaFields = this.getConfig('metaFields'); + + this.fields = new FieldList(this, [], this.shortDotsEnable); + this.fieldsFetcher = createFieldsFetcher(this, apiClient, this.getConfig('metaFields')); + this.flattenHit = flattenHitWrapper(this, this.getConfig('metaFields')); + this.formatHit = formatHitProvider(this, fieldFormats.getDefaultInstance('string')); + this.formatField = this.formatHit.formatField; + } + + private serializeFieldFormatMap(flat: any, format: string, field: string | undefined) { + if (format && field) { + flat[field] = format; + } + } + + private deserializeFieldFormatMap(mapping: any) { + const FieldFormat = fieldFormats.byId[mapping.id]; + return FieldFormat && new FieldFormat(mapping.params, this.getConfig); + } + + private initFields(input?: any) { + const newValue = input || this.fields; + this.fields = new FieldList(this, newValue, this.shortDotsEnable); + } + + private isFieldRefreshRequired(): boolean { + if (!this.fields) { + return true; + } + + return this.fields.every(field => { + // See https://github.com/elastic/kibana/pull/8421 + const hasFieldCaps = 'aggregatable' in field && 'searchable' in field; + + // See https://github.com/elastic/kibana/pull/11969 + const hasDocValuesFlag = 'readFromDocValues' in field; + + return !hasFieldCaps || !hasDocValuesFlag; + }); + } + + private async indexFields(forceFieldRefresh: boolean = false) { + if (!this.id) { + return; + } + + if (forceFieldRefresh || this.isFieldRefreshRequired()) { + await this.refreshFields(); + } + + this.initFields(); + } + + private updateFromElasticSearch(response: any, forceFieldRefresh: boolean = false) { + if (!response.found) { + throw new SavedObjectNotFound(type, this.id, '#/management/kibana/index_pattern'); + } + + _.forOwn(this.mapping, (fieldMapping: FieldMappingSpec, name: string | undefined) => { + if (!fieldMapping._deserialize || !name) { + return; + } + response._source[name] = fieldMapping._deserialize(response._source[name]); + }); + + // give index pattern all of the values in _source + _.assign(this, response._source); + + if (!this.title && this.id) { + this.title = this.id; + } + + return this.indexFields(forceFieldRefresh); + } + + public get routes() { + return getRoutes(); + } + + getComputedFields() { + const scriptFields: any = {}; + if (!this.fields) { + return { + storedFields: ['*'], + scriptFields, + docvalueFields: [], + }; + } + + // Date value returned in "_source" could be in any number of formats + // Use a docvalue for each date field to ensure standardized formats when working with date fields + // indexPattern.flattenHit will override "_source" values when the same field is also defined in "fields" + const docvalueFields = reject(this.fields.byType.date, 'scripted').map((dateField: any) => { + return { + field: dateField.name, + format: + dateField.esTypes && dateField.esTypes.indexOf('date_nanos') !== -1 + ? 'strict_date_time' + : 'date_time', + }; + }); + + each(this.getScriptedFields(), function(field) { + scriptFields[field.name] = { + script: { + source: field.script, + lang: field.lang, + }, + }; + }); + + return { + storedFields: ['*'], + scriptFields, + docvalueFields, + }; + } + + async init(forceFieldRefresh = false) { + if (!this.id) { + return this; // no id === no elasticsearch document + } + + const savedObject = await this.savedObjectsClient.get(type, this.id); + this.version = savedObject._version; + + const response = { + _id: savedObject.id, + _type: savedObject.type, + _source: _.cloneDeep(savedObject.attributes), + found: savedObject._version ? true : false, + }; + // 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, forceFieldRefresh); + // Do it after to ensure we have the most up to date information + this.originalBody = this.prepBody(); + + return this; + } + + // 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) { + const scriptedFields = this.getScriptedFields(); + const names = _.pluck(scriptedFields, 'name'); + + if (_.contains(names, name)) { + throw new DuplicateField(name); + } + + this.fields.push( + new Field(this, { + name, + script, + fieldType, + scripted: true, + lang, + aggregatable: true, + filterable: true, + searchable: true, + }) + ); + + await this.save(); + } + + removeScriptedField(name: string) { + const fieldIndex = _.findIndex(this.fields, { + name, + scripted: true, + }); + + if (fieldIndex > -1) { + this.fields.splice(fieldIndex, 1); + delete this.fieldFormatMap[name]; + return this.save(); + } + } + + async popularizeField(fieldName: string, unit = 1) { + const field = this.fields.byName[fieldName]; + if (!field) { + return; + } + const count = Math.max((field.count || 0) + unit, 0); + if (field.count === count) { + return; + } + field.count = count; + await this.save(); + } + + getNonScriptedFields() { + return _.where(this.fields, { scripted: false }); + } + + getScriptedFields() { + return _.where(this.fields, { scripted: true }); + } + + isTimeBased(): boolean { + return !!this.timeFieldName && (!this.fields || !!this.getTimeField()); + } + + isTimeNanosBased(): boolean { + const timeField: any = this.getTimeField(); + 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.byName) return; + return this.fields.byName[this.timeFieldName]; + } + + getFieldByName(name: string): Field | void { + if (!this.fields || !this.fields.byName) return; + return this.fields.byName[name]; + } + + isWildcard() { + return _.includes(this.title, '*'); + } + + prepBody() { + const body: { [key: string]: any } = {}; + + // serialize json fields + _.forOwn(this.mapping, (fieldMapping, fieldName) => { + if (!fieldName || this[fieldName] == null) return; + + body[fieldName] = fieldMapping._serialize + ? fieldMapping._serialize(this[fieldName]) + : this[fieldName]; + }); + + return body; + } + + async create(allowOverride: boolean = false) { + const _create = async (duplicateId?: string) => { + if (duplicateId) { + const duplicatePattern = new IndexPattern( + duplicateId, + this.getConfig, + this.savedObjectsClient, + this.patternCache, + this.fieldsFetcher + ); + await duplicatePattern.destroy(); + } + + const body = this.prepBody(); + const response = await this.savedObjectsClient.create(type, body, { id: this.id }); + + this.id = response.id; + return response.id; + }; + + const potentialDuplicateByTitle = await findObjectByTitle( + this.savedObjectsClient, + type, + 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 save(saveAttempts: number = 0): Promise { + if (!this.id) return; + const body = this.prepBody(); + // What keys changed since they last pulled the index pattern + const originalChangedKeys = Object.keys(body).filter( + key => body[key] !== this.originalBody[key] + ); + return this.savedObjectsClient + .update(type, this.id, body, { version: this.version }) + .then((resp: any) => { + this.id = resp.id; + this.version = resp._version; + }) + .catch(err => { + if ( + _.get(err, 'res.status') === 409 && + saveAttempts++ < MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS + ) { + const samePattern = new IndexPattern( + this.id, + this.getConfig, + this.savedObjectsClient, + this.patternCache, + this.fieldsFetcher + ); + 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 = Object.keys(updatedBody).filter(key => { + return updatedBody[key] !== body[key] && this.originalBody[key] !== updatedBody[key]; + }); + + let unresolvedCollision = false; + for (const originalKey of originalChangedKeys) { + for (const serverKey of serverChangedKeys) { + if (originalKey === serverKey) { + unresolvedCollision = true; + break; + } + } + } + + if (unresolvedCollision) { + const message = 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.', + } // eslint-disable-line max-len + ); + toastNotifications.addDanger(message); + throw err; + } + + // Set the updated response on this object + serverChangedKeys.forEach(key => { + this[key] = samePattern[key]; + }); + this.version = samePattern.version; + + // Clear cache + this.patternCache.clear(this.id); + + // Try the save again + return this.save(saveAttempts); + }); + } + throw err; + }); + } + + async _fetchFields() { + const fields = await this.fieldsFetcher.fetch(this); + const scripted = this.getScriptedFields(); + const all = fields.concat(scripted); + await this.initFields(all); + } + + refreshFields() { + return this._fetchFields() + .then(() => this.save()) + .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) { + toastNotifications.addDanger((err as any).message); + return []; + } + + toastNotifications.addError(err, { + title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { + defaultMessage: 'Error fetching fields', + }), + }); + throw err; + }); + } + + toJSON() { + return this.id; + } + + toString() { + return '' + this.toJSON(); + } + + destroy() { + this.patternCache.clear(this.id); + if (this.id) { + return this.savedObjectsClient.delete(type, this.id); + } + } +} diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts new file mode 100644 index 0000000000000..8fc5c89e5d17c --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.test.ts @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 { IndexPatterns } from './index_patterns'; +import { SavedObjectsClientContract, UiSettingsClientContract } from 'kibana/public'; + +jest.mock('../errors', () => ({ + IndexPatternMissingIndices: jest.fn(), +})); + +jest.mock('ui/registry/field_formats', () => ({ + fieldFormats: { + getDefaultInstance: jest.fn(), + }, +})); + +jest.mock('ui/notify', () => ({ + toastNotifications: { + addDanger: jest.fn(), + }, +})); + +jest.mock('./index_pattern', () => { + class IndexPattern { + init = async () => { + return this; + }; + } + + return { + IndexPattern, + }; +}); + +jest.mock('./index_patterns_api_client', () => { + class IndexPatternsApiClient { + getFieldsForWildcard = async () => ({}); + } + + return { + IndexPatternsApiClient, + }; +}); + +describe('IndexPatterns', () => { + let indexPatterns: IndexPatterns; + + beforeEach(() => { + const savedObjectsClient = {} as SavedObjectsClientContract; + const uiSettings = {} as UiSettingsClientContract; + + indexPatterns = new IndexPatterns(uiSettings, savedObjectsClient); + }); + + test('does not cache gets without an id', () => { + expect(indexPatterns.get()).not.toBe(indexPatterns.get()); + }); + + test('does cache gets for the same id', () => { + const id = '1'; + + expect(indexPatterns.get(id)).toBe(indexPatterns.get(id)); + }); +}); diff --git a/src/legacy/ui/public/index_patterns/index_patterns.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts similarity index 93% rename from src/legacy/ui/public/index_patterns/index_patterns.ts rename to src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts index 412a9b684a105..b121a7667c79b 100644 --- a/src/legacy/ui/public/index_patterns/index_patterns.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns.ts @@ -18,14 +18,17 @@ */ import { idx } from '@kbn/elastic-idx'; -import { SavedObjectsClientContract, SimpleSavedObject } from 'src/core/public'; +import { + SavedObjectsClientContract, + SimpleSavedObject, + UiSettingsClientContract, +} from 'src/core/public'; // @ts-ignore -import { fieldFormats } from '../registry/field_formats'; +import { fieldFormats } from 'ui/registry/field_formats'; -import { IndexPattern } from './_index_pattern'; import { createIndexPatternCache } from './_pattern_cache'; +import { IndexPattern } from './index_pattern'; import { IndexPatternsApiClient } from './index_patterns_api_client'; -import { UiSettingsClientContract } from '../../../../core/public'; const indexPatternCache = createIndexPatternCache(); const apiClient = new IndexPatternsApiClient(); @@ -122,7 +125,8 @@ export class IndexPatterns { // add angular service for backward compatibility // @ts-ignore -import { uiModules } from '../modules'; +// eslint-disable-next-line +import { uiModules } from 'ui/modules'; const module = uiModules.get('kibana/index_patterns'); let _service: any; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.mock.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.mock.ts new file mode 100644 index 0000000000000..06933dc409052 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.mock.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 { setup } from '../../../../../../test_utils/public/http_test_setup'; + +export const { http } = setup(injectedMetadata => { + injectedMetadata.getBasePath.mockReturnValue('/hola/daro/'); +}); + +jest.doMock('ui/new_platform', () => ({ npSetup: { core: { http } } })); diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.ts new file mode 100644 index 0000000000000..944108e1501f1 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.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 { http } from './index_patterns_api_client.test.mock'; +import { IndexPatternsApiClient } from './index_patterns_api_client'; + +const requestData = { + credentials: 'same-origin', + headers: { 'Content-Type': 'application/json' }, + method: 'GET', + prependBasePath: true, + query: {}, +}; + +describe('IndexPatternsApiClient', () => { + let fetchSpy: jest.Mock; + let indexPatternsApiClient: IndexPatternsApiClient; + + beforeEach(() => { + fetchSpy = jest.spyOn(http, 'fetch').mockImplementation(() => Promise.resolve({})); + indexPatternsApiClient = new IndexPatternsApiClient(); + }); + + test('uses the right URI to fetch fields for time patterns', async function() { + const expectedPath = '/api/index_patterns/_fields_for_time_pattern'; + + await indexPatternsApiClient.getFieldsForTimePattern(); + + expect(fetchSpy).toHaveBeenCalledWith(expectedPath, requestData); + }); + + test('uses the right URI to fetch fields for wildcard', async function() { + const expectedPath = '/api/index_patterns/_fields_for_wildcard'; + + await indexPatternsApiClient.getFieldsForWildcard(); + + expect(fetchSpy).toHaveBeenCalledWith(expectedPath, requestData); + }); + + test('uses the right URI to fetch fields for wildcard given a type', async function() { + const expectedPath = '/api/index_patterns/rollup/_fields_for_wildcard'; + + await indexPatternsApiClient.getFieldsForWildcard({ type: 'rollup' }); + + expect(fetchSpy).toHaveBeenCalledWith(expectedPath, requestData); + }); +}); diff --git a/src/legacy/ui/public/index_patterns/index_patterns_api_client.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts similarity index 95% rename from src/legacy/ui/public/index_patterns/index_patterns_api_client.ts rename to src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts index ae71157aea829..4b0d7ec08347b 100644 --- a/src/legacy/ui/public/index_patterns/index_patterns_api_client.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts @@ -17,9 +17,9 @@ * under the License. */ -import { kfetch, KFetchQuery } from '../kfetch'; +import { kfetch, KFetchQuery } from 'ui/kfetch'; -import { IndexPatternMissingIndices } from './errors'; +import { IndexPatternMissingIndices } from '../errors'; function request(url: string, query: KFetchQuery) { return kfetch({ diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.mock.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.mock.ts new file mode 100644 index 0000000000000..d4e5cc011d5f3 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.mock.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 { IndexPatternsService, IndexPatternsSetup } from '.'; +// @ts-ignore +import { flattenHitWrapper } from './index_patterns/flatten_hit'; + +type IndexPatternsServiceClientContract = PublicMethodsOf; + +const createSetupContractMock = () => { + // Legacy mock - must be removed before migrating to new platform. + // Included here because we only want to call `jest.mock` when somebody creates + // the mock for this contract. + jest.mock('ui/chrome'); + + const setupContract: jest.Mocked = { + FieldList: {} as any, + flattenHitWrapper: jest.fn().mockImplementation(flattenHitWrapper), + formatHitProvider: jest.fn(), + indexPatterns: jest.fn() as any, + IndexPatternSelect: jest.fn(), + __LEGACY: { + // For BWC we must temporarily export the class implementation of Field, + // which is only used externally by the Index Pattern UI. + FieldImpl: jest.fn(), + }, + }; + + return setupContract; +}; + +const createMock = () => { + const mocked: jest.Mocked = { + setup: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + }; + + mocked.setup.mockReturnValue(createSetupContractMock()); + return mocked; +}; + +export const indexPatternsServiceMock = { + create: createMock, + createSetupContract: createSetupContractMock, + createStartContract: createSetupContractMock, +}; diff --git a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts index 4ab08c2a60eb0..8ecca8fa94a14 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/index_patterns_service.ts @@ -16,25 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -// @ts-ignore -import { mockFields, mockIndexPattern } from 'ui/index_patterns/fixtures'; -// @ts-ignore -import { INDEX_PATTERN_ILLEGAL_CHARACTERS } from 'ui/index_patterns/index'; -// @ts-ignore -import { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/index_patterns/index'; -// @ts-ignore -import { IndexPatternSelect } from 'ui/index_patterns/index'; -// @ts-ignore -import { IndexPatterns } from 'ui/index_patterns/index'; -// @ts-ignore -import { validateIndexPattern } from 'ui/index_patterns/index'; - -import { isFilterable, getFromSavedObject } from 'ui/index_patterns/static_utils'; - -// IndexPattern, StaticIndexPattern, Field -import * as types from 'ui/index_patterns'; import { UiSettingsClientContract, SavedObjectsClientContract } from 'src/core/public'; +import { Field, FieldList, FieldType } from './fields'; +// @ts-ignore +import { createFlattenHitWrapper } from './index_patterns/flatten_hit'; +import { createIndexPatternSelect } from './components'; +import { + formatHitProvider, + IndexPattern, + IndexPatterns, + StaticIndexPattern, +} from './index_patterns'; export interface IndexPatternDependencies { uiSettings: UiSettingsClientContract; @@ -44,60 +37,75 @@ export interface IndexPatternDependencies { /** * Index Patterns Service * - * The `setup` method of this service returns the public contract for - * index patterns. Right now these APIs are simply imported from `ui/public` - * and re-exported here. Once the index patterns code actually moves to - * this plugin, the imports above can simply be updated to point to their - * corresponding local directory. - * * @internal */ export class IndexPatternsService { public setup({ uiSettings, savedObjectsClient }: IndexPatternDependencies) { return { + FieldList, + flattenHitWrapper: createFlattenHitWrapper(), + formatHitProvider, indexPatterns: new IndexPatterns(uiSettings, savedObjectsClient), + IndexPatternSelect: createIndexPatternSelect(savedObjectsClient), + __LEGACY: { + // For BWC we must temporarily export the class implementation of Field, + // which is only used externally by the Index Pattern UI. + FieldImpl: Field, + }, }; } + public start() { + // nothing to do here yet + } + public stop() { // nothing to do here yet } } -// static exports +// static code -const constants = { +/** @public */ +export { IndexPatternSelect } from './components'; +export { IndexPatternsProvider } from './index_patterns'; +export { + CONTAINS_SPACES, + getFromSavedObject, + getRoutes, + ILLEGAL_CHARACTERS, INDEX_PATTERN_ILLEGAL_CHARACTERS, INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE, -}; - -const fixtures = { + isFilterable, + validateIndexPattern, mockFields, mockIndexPattern, -}; +} from './utils'; -const ui = { - IndexPatternSelect, -}; +/** @public */ +export { + IndexPatternAlreadyExists, + IndexPatternMissingIndices, + NoDefaultIndexPattern, + NoDefinedIndexPatterns, +} from './errors'; -const utils = { - getFromSavedObject, - isFilterable, -}; +// types -export { validateIndexPattern, constants, fixtures, ui, IndexPatterns, utils }; +/** @internal */ +export type IndexPatternsSetup = ReturnType; /** @public */ -export type IndexPatternsSetup = ReturnType; +export type IndexPattern = IndexPattern; /** @public */ -export type IndexPattern = types.IndexPattern; +export type IndexPatterns = IndexPatterns; /** @public */ -export type StaticIndexPattern = types.StaticIndexPattern; +export type StaticIndexPattern = StaticIndexPattern; /** @public */ -export type Field = types.Field; +export type Field = Field; /** @public */ -export type FieldType = types.FieldType; +export type FieldType = FieldType; diff --git a/src/legacy/core_plugins/data/public/index_patterns/utils.test.ts b/src/legacy/core_plugins/data/public/index_patterns/utils.test.ts new file mode 100644 index 0000000000000..1a186a6514763 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/utils.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 { + CONTAINS_SPACES, + ILLEGAL_CHARACTERS, + INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE, + isFilterable, + validateIndexPattern, +} from './utils'; + +import { Field } from './fields'; + +const mockField = { + name: 'foo', + scripted: false, + searchable: true, + type: 'string', +} as Field; + +describe('Index Pattern Utils', () => { + describe('Validation', () => { + it('should not allow space in the pattern', () => { + const errors = validateIndexPattern('my pattern'); + expect(errors[CONTAINS_SPACES]).toBe(true); + }); + + it('should not allow illegal characters', () => { + INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.forEach(char => { + const errors = validateIndexPattern(`pattern${char}`); + expect(errors[ILLEGAL_CHARACTERS]).toEqual([char]); + }); + }); + + it('should return empty object when there are no errors', () => { + expect(validateIndexPattern('my-pattern-*')).toEqual({}); + }); + }); + + describe('isFilterable', () => { + describe('types', () => { + it('should return true for filterable types', () => { + ['string', 'number', 'date', 'ip', 'boolean'].forEach(type => { + expect(isFilterable({ ...mockField, type })).toBe(true); + }); + }); + + it('should return false for filterable types if the field is not searchable', () => { + ['string', 'number', 'date', 'ip', 'boolean'].forEach(type => { + expect(isFilterable({ ...mockField, type, searchable: false })).toBe(false); + }); + }); + + it('should return false for un-filterable types', () => { + [ + 'geo_point', + 'geo_shape', + 'attachment', + 'murmur3', + '_source', + 'unknown', + 'conflict', + ].forEach(type => { + expect(isFilterable({ ...mockField, type })).toBe(false); + }); + }); + }); + + it('should return true for scripted fields', () => { + expect(isFilterable({ ...mockField, scripted: true, searchable: false })).toBe(true); + }); + + it('should return true for the _id field', () => { + expect(isFilterable({ ...mockField, name: '_id' })).toBe(true); + }); + }); +}); diff --git a/src/legacy/core_plugins/data/public/index_patterns/utils.ts b/src/legacy/core_plugins/data/public/index_patterns/utils.ts new file mode 100644 index 0000000000000..90a6554f399b8 --- /dev/null +++ b/src/legacy/core_plugins/data/public/index_patterns/utils.ts @@ -0,0 +1,166 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +import { get } from 'lodash'; +// @ts-ignore +import { KBN_FIELD_TYPES } from '../../../../utils/kbn_field_types'; +import { Field, FieldType } from './fields'; +import { StaticIndexPattern } from './index_patterns'; + +export const ILLEGAL_CHARACTERS = 'ILLEGAL_CHARACTERS'; +export const CONTAINS_SPACES = 'CONTAINS_SPACES'; +export const INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE = ['\\', '/', '?', '"', '<', '>', '|']; +export const INDEX_PATTERN_ILLEGAL_CHARACTERS = INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.concat( + ' ' +); + +function findIllegalCharacters(indexPattern: string): string[] { + const illegalCharacters = INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.reduce( + (chars: string[], char: string) => { + if (indexPattern.includes(char)) { + chars.push(char); + } + return chars; + }, + [] + ); + + return illegalCharacters; +} + +function indexPatternContainsSpaces(indexPattern: string): boolean { + return indexPattern.includes(' '); +} + +export function validateIndexPattern(indexPattern: string) { + const errors: Record = {}; + + const illegalCharacters = findIllegalCharacters(indexPattern); + + if (illegalCharacters.length) { + errors[ILLEGAL_CHARACTERS] = illegalCharacters; + } + + if (indexPatternContainsSpaces(indexPattern)) { + errors[CONTAINS_SPACES] = true; + } + + return errors; +} + +const filterableTypes = KBN_FIELD_TYPES.filter((type: any) => type.filterable).map( + (type: any) => type.name +); + +export function isFilterable(field: Field): boolean { + return ( + field.name === '_id' || + field.scripted || + (field.searchable && filterableTypes.includes(field.type)) + ); +} + +export function getFromSavedObject(savedObject: any) { + if (get(savedObject, 'attributes.fields') === undefined) { + return; + } + + return { + id: savedObject.id, + fields: JSON.parse(savedObject.attributes.fields), + title: savedObject.attributes.title, + }; +} + +export function getRoutes() { + return { + edit: '/management/kibana/index_patterns/{{id}}', + addField: '/management/kibana/index_patterns/{{id}}/create-field', + indexedFields: '/management/kibana/index_patterns/{{id}}?_a=(tab:indexedFields)', + scriptedFields: '/management/kibana/index_patterns/{{id}}?_a=(tab:scriptedFields)', + sourceFilters: '/management/kibana/index_patterns/{{id}}?_a=(tab:sourceFilters)', + }; +} + +export const mockFields: FieldType[] = [ + { + name: 'machine.os', + esTypes: ['text'], + type: 'string', + aggregatable: false, + searchable: false, + filterable: true, + }, + { + name: 'machine.os.raw', + type: 'string', + esTypes: ['keyword'], + aggregatable: true, + searchable: true, + filterable: true, + }, + { + name: 'not.filterable', + type: 'string', + esTypes: ['text'], + aggregatable: true, + searchable: false, + filterable: false, + }, + { + name: 'bytes', + type: 'number', + esTypes: ['long'], + aggregatable: true, + searchable: true, + filterable: true, + }, + { + name: '@timestamp', + type: 'date', + esTypes: ['date'], + aggregatable: true, + searchable: true, + filterable: true, + }, + { + name: 'clientip', + type: 'ip', + esTypes: ['ip'], + aggregatable: true, + searchable: true, + filterable: true, + }, + { + name: 'bool.field', + type: 'boolean', + esTypes: ['boolean'], + aggregatable: true, + searchable: true, + filterable: true, + }, +]; + +export const mockIndexPattern: StaticIndexPattern = { + id: 'logstash-*', + fields: mockFields, + title: 'logstash-*', + timeFieldName: '@timestamp', +}; diff --git a/src/legacy/core_plugins/data/public/legacy.ts b/src/legacy/core_plugins/data/public/legacy.ts index 14350a6284191..c3618d412f425 100644 --- a/src/legacy/core_plugins/data/public/legacy.ts +++ b/src/legacy/core_plugins/data/public/legacy.ts @@ -34,11 +34,7 @@ * data that will eventually be injected by the new platform. */ -import { npSetup } from 'ui/new_platform'; -// @ts-ignore -import { renderersRegistry } from 'plugins/interpreter/registries'; -// @ts-ignore -import { getInterpreter } from 'plugins/interpreter/interpreter'; +import { npSetup, npStart } from 'ui/new_platform'; import { LegacyDependenciesPlugin } from './shim/legacy_dependencies_plugin'; import { plugin } from '.'; @@ -47,8 +43,6 @@ const legacyPlugin = new LegacyDependenciesPlugin(); export const setup = dataPlugin.setup(npSetup.core, { __LEGACY: legacyPlugin.setup(), - interpreter: { - renderersRegistry, - getInterpreter, - }, }); + +export const start = dataPlugin.start(npStart.core); diff --git a/src/legacy/core_plugins/data/public/mocks.ts b/src/legacy/core_plugins/data/public/mocks.ts new file mode 100644 index 0000000000000..0ca0b4947d538 --- /dev/null +++ b/src/legacy/core_plugins/data/public/mocks.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 { DataSetup } from '.'; +import { filterServiceMock } from './filter/filter_service.mock'; +import { indexPatternsServiceMock } from './index_patterns/index_patterns_service.mock'; +import { queryServiceMock } from './query/query_service.mock'; + +function createDataSetupMock() { + const mock: MockedKeys> = { + filter: filterServiceMock.createSetupContract(), + indexPatterns: indexPatternsServiceMock.createSetupContract(), + query: queryServiceMock.createSetupContract(), + }; + + return mock; +} + +function createDataStartMock() { + return {}; +} + +export const dataPluginMock = { + createSetup: createDataSetupMock, + createStart: createDataStartMock, +}; diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 34edb355d2ef8..f63f569534d86 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -18,7 +18,6 @@ */ import { CoreSetup, CoreStart, Plugin } from '../../../../core/public'; -import { ExpressionsService, ExpressionsSetup } from './expressions'; import { SearchService, SearchSetup } from './search'; import { QueryService, QuerySetup } from './query'; import { FilterService, FilterSetup } from './filter'; @@ -32,7 +31,6 @@ import { LegacyDependenciesPluginSetup } from './shim/legacy_dependencies_plugin */ export interface DataPluginSetupDependencies { __LEGACY: LegacyDependenciesPluginSetup; - interpreter: any; } /** @@ -41,7 +39,6 @@ export interface DataPluginSetupDependencies { * @public */ export interface DataSetup { - expressions: ExpressionsSetup; indexPatterns: IndexPatternsSetup; filter: FilterSetup; query: QuerySetup; @@ -59,15 +56,16 @@ export interface DataSetup { * in the setup/start interfaces. The remaining items exported here are either types, * or static code. */ -export class DataPlugin implements Plugin { +export class DataPlugin implements Plugin { // Exposed services, sorted alphabetically - private readonly expressions: ExpressionsService = new ExpressionsService(); private readonly filter: FilterService = new FilterService(); private readonly indexPatterns: IndexPatternsService = new IndexPatternsService(); private readonly query: QueryService = new QueryService(); private readonly search: SearchService = new SearchService(); - public setup(core: CoreSetup, { __LEGACY, interpreter }: DataPluginSetupDependencies): DataSetup { + private setupApi!: DataSetup; + + public setup(core: CoreSetup, { __LEGACY }: DataPluginSetupDependencies): DataSetup { const { uiSettings } = core; const savedObjectsClient = __LEGACY.savedObjectsClient; @@ -75,24 +73,27 @@ export class DataPlugin implements Plugin diff --git a/src/legacy/core_plugins/kibana/public/context/components/loading_button/loading_button.js b/src/legacy/core_plugins/kibana/public/context/components/loading_button/loading_button.js deleted file mode 100644 index 62effb3536a7a..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/components/loading_button/loading_button.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 { uiModules } from 'ui/modules'; -import contextLoadingButtonTemplate from './loading_button.html'; - - -const module = uiModules.get('apps/context', [ - 'kibana', - 'ngRoute', -]); - -module.directive('contextLoadingButton', function ContextLoadingButton() { - return { - replace: true, - restrict: 'E', - scope: { - isDisabled: '=', - icon: '=', - }, - template: contextLoadingButtonTemplate, - transclude: true, - }; -}); diff --git a/src/legacy/core_plugins/kibana/public/context/components/size_picker/_index.scss b/src/legacy/core_plugins/kibana/public/context/components/size_picker/_index.scss deleted file mode 100644 index 6a7ffa7201919..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/components/size_picker/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './size_picker'; diff --git a/src/legacy/core_plugins/kibana/public/context/components/size_picker/_size_picker.scss b/src/legacy/core_plugins/kibana/public/context/components/size_picker/_size_picker.scss deleted file mode 100644 index 3e9b05a2872ca..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/components/size_picker/_size_picker.scss +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 1. Hide increment and decrement buttons for type="number" input. - */ -.cxtSizePicker { - appearance: textfield; - text-align: center; - width: $euiSize * 5; - - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - appearance: none; /* 1 */ - margin: 0; /* 1 */ - } -} diff --git a/src/legacy/core_plugins/kibana/public/context/components/size_picker/index.js b/src/legacy/core_plugins/kibana/public/context/components/size_picker/index.js deleted file mode 100644 index 034044dabff60..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/components/size_picker/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. - */ - -import './size_picker'; diff --git a/src/legacy/core_plugins/kibana/public/context/components/size_picker/size_picker.html b/src/legacy/core_plugins/kibana/public/context/components/size_picker/size_picker.html deleted file mode 100644 index d3bda3268310a..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/components/size_picker/size_picker.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/src/legacy/core_plugins/kibana/public/context/components/size_picker/size_picker.js b/src/legacy/core_plugins/kibana/public/context/components/size_picker/size_picker.js deleted file mode 100644 index c6679b26f4ea3..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/components/size_picker/size_picker.js +++ /dev/null @@ -1,64 +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 _ from 'lodash'; -import { uiModules } from 'ui/modules'; -import { callAfterBindingsWorkaround } from 'ui/compat'; -import contextSizePickerTemplate from './size_picker.html'; - -const module = uiModules.get('apps/context', [ - 'kibana', -]); - -module.directive('contextSizePicker', function ContextSizePicker() { - return { - bindToController: true, - controller: callAfterBindingsWorkaround(ContextSizePickerController), - controllerAs: 'contextSizePicker', - link: linkContextSizePicker, - replace: true, - restrict: 'E', - require: 'ngModel', - scope: { - count: '=', - isDisabled: '=', - onChangeCount: '=', // To avoid inconsistent ngModel states this action - // should make sure the new value is propagated back - // to the `count` property. If that propagation - // fails, the user input will be reset to the value - // of `count`. - }, - template: contextSizePickerTemplate, - }; -}); - -function linkContextSizePicker(scope, element, attrs, ngModel) { - scope.countModel = ngModel; -} - -function ContextSizePickerController($scope) { - $scope.$watch( - () => this.count, - () => $scope.countModel.$rollbackViewValue(), - ); - - this.getOrSetCount = (count) => ( - _.isUndefined(count) ? this.count : this.onChangeCount(count) - ); -} diff --git a/src/legacy/core_plugins/kibana/public/context/index.html b/src/legacy/core_plugins/kibana/public/context/index.html index 231457ecae4e2..1c870f56a1118 100644 --- a/src/legacy/core_plugins/kibana/public/context/index.html +++ b/src/legacy/core_plugins/kibana/public/context/index.html @@ -1,5 +1,4 @@ { + const { indexPattern } = $route.current.locals; + const { id } = $route.current.params; + + return [ + ...getRootBreadcrumbs(), + { + text: i18n.translate('kbn.context.breadcrumb', { + defaultMessage: 'Context of {indexPatternTitle}#{docId}', + values: { + indexPatternTitle: indexPattern.title, + docId: id, + }, + }), + }, + ]; +}; + + uiRoutes + // 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($route) { - const { indexPattern } = $route.current.locals; - const { id } = $route.current.params; - - return [ - ...getRootBreadcrumbs(), - { - text: i18n.translate('kbn.context.breadcrumb', { - defaultMessage: 'Context of {indexPatternTitle}#{docId}', - values: { - indexPatternTitle: indexPattern.title, - docId: id - } - }) - } - ]; - }, + k7Breadcrumbs, controllerAs: 'contextAppRoute', resolve: { indexPattern: function ($route, indexPatterns) { @@ -58,37 +66,30 @@ uiRoutes template: contextAppRouteTemplate, }); - -function ContextAppRouteController( - $routeParams, - $scope, - AppState, - config, - indexPattern, - Private, -) { +function ContextAppRouteController($routeParams, $scope, AppState, config, indexPattern, Private) { const queryFilter = Private(FilterBarQueryFilterProvider); this.state = new AppState(createDefaultAppState(config, indexPattern)); this.state.save(true); - $scope.$watchGroup([ - 'contextAppRoute.state.columns', - 'contextAppRoute.state.predecessorCount', - 'contextAppRoute.state.successorCount', - ], () => this.state.save(true)); + $scope.$watchGroup( + [ + 'contextAppRoute.state.columns', + 'contextAppRoute.state.predecessorCount', + 'contextAppRoute.state.successorCount', + ], + () => this.state.save(true) + ); const updateSubsciption = subscribeWithScope($scope, queryFilter.getUpdates$(), { next: () => { this.filters = _.cloneDeep(queryFilter.getFilters()); - } + }, }); $scope.$on('$destroy', function () { updateSubsciption.unsubscribe(); }); - - this.anchorType = $routeParams.type; this.anchorId = $routeParams.id; this.indexPattern = indexPattern; this.discoverUrl = npStart.core.chrome.navLinks.get('kibana:discover').url; diff --git a/src/legacy/core_plugins/kibana/public/context/query/actions.js b/src/legacy/core_plugins/kibana/public/context/query/actions.js index b61a1f8f687ee..72624210fcb49 100644 --- a/src/legacy/core_plugins/kibana/public/context/query/actions.js +++ b/src/legacy/core_plugins/kibana/public/context/query/actions.js @@ -20,20 +20,18 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { MarkdownSimple } from 'ui/markdown'; import { toastNotifications } from 'ui/notify'; import { fetchAnchorProvider } from '../api/anchor'; import { fetchContextProvider } from '../api/context'; import { QueryParameterActionsProvider } from '../query_parameters'; import { FAILURE_REASONS, LOADING_STATUS } from './constants'; +import { MarkdownSimple } from '../../../../kibana_react/public'; export function QueryActionsProvider(Private, Promise) { const fetchAnchor = Private(fetchAnchorProvider); const { fetchSurroundingDocs } = Private(fetchContextProvider); const { - increasePredecessorCount, - increaseSuccessorCount, setPredecessorCount, setQueryParameters, setSuccessorCount, @@ -60,7 +58,7 @@ export function QueryActionsProvider(Private, Promise) { ); const fetchAnchorRow = (state) => () => { - const { queryParameters: { indexPatternId, anchorType, anchorId, sort, tieBreakerField } } = state; + const { queryParameters: { indexPatternId, anchorId, sort, tieBreakerField } } = state; if (!tieBreakerField) { return Promise.reject(setFailedStatus(state)('anchor', { @@ -71,7 +69,7 @@ export function QueryActionsProvider(Private, Promise) { setLoadingStatus(state)('anchor'); return Promise.try(() => ( - fetchAnchor(indexPatternId, anchorType, anchorId, [_.zipObject([sort]), { [tieBreakerField]: sort[1] }]) + fetchAnchor(indexPatternId, anchorId, [_.zipObject([sort]), { [tieBreakerField]: sort[1] }]) )) .then( (anchorDocument) => { @@ -173,16 +171,6 @@ export function QueryActionsProvider(Private, Promise) { return fetchSurroundingRows('successors', state); }; - const fetchMorePredecessorRows = (state) => () => { - increasePredecessorCount(state)(); - return fetchSurroundingRows('predecessors', state); - }; - - const fetchMoreSuccessorRows = (state) => () => { - increaseSuccessorCount(state)(); - return fetchSurroundingRows('successors', state); - }; - const setAllRows = (state) => (predecessorRows, anchorRow, successorRows) => ( state.rows.all = [ ...(predecessorRows || []), @@ -199,8 +187,6 @@ export function QueryActionsProvider(Private, Promise) { fetchContextRowsWithNewQueryParameters, fetchGivenPredecessorRows, fetchGivenSuccessorRows, - fetchMorePredecessorRows, - fetchMoreSuccessorRows, setAllRows, }; } diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_predecessor_count.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_predecessor_count.js deleted file mode 100644 index cd19f7af8d829..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_predecessor_count.js +++ /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 expect from '@kbn/expect'; -import ngMock from 'ng_mock'; - -import { createStateStub } from './_utils'; -import { QueryParameterActionsProvider } from '../actions'; - - -describe('context app', function () { - beforeEach(ngMock.module('kibana')); - - describe('action increasePredecessorCount', function () { - let increasePredecessorCount; - - beforeEach(ngMock.inject(function createPrivateStubs(Private) { - increasePredecessorCount = Private(QueryParameterActionsProvider).increasePredecessorCount; - })); - - it('should increase the predecessorCount by the given value', function () { - const state = createStateStub(); - - increasePredecessorCount(state)(20); - - expect(state.queryParameters.predecessorCount).to.equal(30); - }); - - it('should increase the predecessorCount by the default step size if not value is given', function () { - const state = createStateStub(); - - increasePredecessorCount(state)(); - - expect(state.queryParameters.predecessorCount).to.equal(13); - }); - - it('should limit the predecessorCount to 0 as a lower bound', function () { - const state = createStateStub(); - - increasePredecessorCount(state)(-20); - - expect(state.queryParameters.predecessorCount).to.equal(0); - }); - - it('should limit the predecessorCount to 10000 as an upper bound', function () { - const state = createStateStub(); - - increasePredecessorCount(state)(20000); - - expect(state.queryParameters.predecessorCount).to.equal(10000); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_successor_count.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_successor_count.js deleted file mode 100644 index 7036df1ea626f..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_increase_successor_count.js +++ /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 expect from '@kbn/expect'; -import ngMock from 'ng_mock'; - -import { createStateStub } from './_utils'; -import { QueryParameterActionsProvider } from '../actions'; - - -describe('context app', function () { - beforeEach(ngMock.module('kibana')); - - describe('action increaseSuccessorCount', function () { - let increaseSuccessorCount; - - beforeEach(ngMock.inject(function createPrivateStubs(Private) { - increaseSuccessorCount = Private(QueryParameterActionsProvider).increaseSuccessorCount; - })); - - it('should increase the successorCount by the given value', function () { - const state = createStateStub(); - - increaseSuccessorCount(state)(20); - - expect(state.queryParameters.successorCount).to.equal(30); - }); - - it('should increase the successorCount by the default step size if not value is given', function () { - const state = createStateStub(); - - increaseSuccessorCount(state)(); - - expect(state.queryParameters.successorCount).to.equal(13); - }); - - it('should limit the successorCount to 0 as a lower bound', function () { - const state = createStateStub(); - - increaseSuccessorCount(state)(-20); - - expect(state.queryParameters.successorCount).to.equal(0); - }); - - it('should limit the successorCount to 10000 as an upper bound', function () { - const state = createStateStub(); - - increaseSuccessorCount(state)(20000); - - expect(state.queryParameters.successorCount).to.equal(10000); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js index c64a1d40ea43c..853c5726b3da5 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/__tests__/action_set_query_parameters.js @@ -42,7 +42,6 @@ describe('context app', function () { }); setQueryParameters(state)({ - anchorType: 'ANCHOR_TYPE', anchorId: 'ANCHOR_ID', columns: ['column'], defaultStepSize: 3, @@ -55,7 +54,6 @@ describe('context app', function () { expect(state.queryParameters).to.eql({ additionalParameter: 'ADDITIONAL_PARAMETER', - anchorType: 'ANCHOR_TYPE', anchorId: 'ANCHOR_ID', columns: ['column'], defaultStepSize: 3, diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/actions.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/actions.js index cd5af188ad321..1c895b8d9e1c5 100644 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/actions.js +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/actions.js @@ -40,12 +40,6 @@ export function QueryParameterActionsProvider(indexPatterns, Private) { ) ); - const increasePredecessorCount = (state) => ( - value = state.queryParameters.defaultStepSize, - ) => ( - setPredecessorCount(state)(state.queryParameters.predecessorCount + value) - ); - const setSuccessorCount = (state) => (successorCount) => ( state.queryParameters.successorCount = clamp( MIN_CONTEXT_SIZE, @@ -54,12 +48,6 @@ export function QueryParameterActionsProvider(indexPatterns, Private) { ) ); - const increaseSuccessorCount = (state) => ( - value = state.queryParameters.defaultStepSize, - ) => ( - setSuccessorCount(state)(state.queryParameters.successorCount + value) - ); - const setQueryParameters = (state) => (queryParameters) => ( Object.assign( state.queryParameters, @@ -82,8 +70,6 @@ export function QueryParameterActionsProvider(indexPatterns, Private) { return { addFilter, updateFilters, - increasePredecessorCount, - increaseSuccessorCount, setPredecessorCount, setQueryParameters, setSuccessorCount, diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/constants.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/constants.js deleted file mode 100644 index 9b9e93f7ba000..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/constants.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 { createInitialQueryParametersState } from './state'; - - -export const MAX_CONTEXT_SIZE = 10000; // Elasticsearch's default maximum size limit -export const MIN_CONTEXT_SIZE = 0; -export const QUERY_PARAMETER_KEYS = Object.keys(createInitialQueryParametersState()); diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/constants.ts b/src/legacy/core_plugins/kibana/public/context/query_parameters/constants.ts new file mode 100644 index 0000000000000..9fdf79a714e78 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/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 { createInitialQueryParametersState } from './state'; + +export const MAX_CONTEXT_SIZE = 10000; // Elasticsearch's default maximum size limit +export const MIN_CONTEXT_SIZE = 0; +export const QUERY_PARAMETER_KEYS = Object.keys(createInitialQueryParametersState()); diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/state.js b/src/legacy/core_plugins/kibana/public/context/query_parameters/state.js deleted file mode 100644 index bc3cbae82037c..0000000000000 --- a/src/legacy/core_plugins/kibana/public/context/query_parameters/state.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. - */ - -export function createInitialQueryParametersState(defaultStepSize, tieBreakerField) { - return { - anchorType: null, - anchorId: null, - columns: [], - defaultStepSize, - filters: [], - indexPatternId: null, - predecessorCount: 0, - successorCount: 0, - sort: [], - tieBreakerField, - }; -} diff --git a/src/legacy/core_plugins/kibana/public/context/query_parameters/state.ts b/src/legacy/core_plugins/kibana/public/context/query_parameters/state.ts new file mode 100644 index 0000000000000..094dba6341d0c --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/context/query_parameters/state.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. + */ + +export function createInitialQueryParametersState( + defaultStepSize: number = 5, + tieBreakerField: string = '_doc' +) { + return { + anchorId: null, + columns: [], + defaultStepSize, + filters: [], + indexPatternId: null, + predecessorCount: 0, + successorCount: 0, + sort: [], + tieBreakerField, + }; +} diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html index bf9d97b3867f6..5ceb28e6b225b 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app.html @@ -3,16 +3,18 @@ ng-class="{'dshAppContainer--withMargins': model.useMargins}" > - - + - - +
    @@ -157,11 +162,13 @@
    -
    -
    + ng-show="vis && rows.length !== 0" + chart-data="histogramData" + timefilter-update-handler="timefilterUpdateHandler" + watch-depth="reference" + >
    + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} void; } export interface SavedSearchLoader { diff --git a/src/legacy/core_plugins/kibana/public/doc/index.html b/src/legacy/core_plugins/kibana/public/doc/index.html index 69f3a6115baee..4357c6aaf78a7 100644 --- a/src/legacy/core_plugins/kibana/public/doc/index.html +++ b/src/legacy/core_plugins/kibana/public/doc/index.html @@ -54,8 +54,8 @@
    -
    - +
    +
    diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap b/src/legacy/core_plugins/kibana/public/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap new file mode 100644 index 0000000000000..d94799e0507e6 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap @@ -0,0 +1,56 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render with 3 different tabs 1`] = ` +
    + , + "id": "Render function", + "name": "Render function", + }, + Object { + "content": , + "id": "React component", + "name": "React component", + }, + Object { + "content": , + "id": "Invalid doc view", + "name": "Invalid doc view", + }, + ] + } + /> +
    +`; diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/__snapshots__/doc_viewer_render_tab.test.tsx.snap b/src/legacy/core_plugins/kibana/public/doc_viewer/__snapshots__/doc_viewer_render_tab.test.tsx.snap new file mode 100644 index 0000000000000..31509659ce419 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/__snapshots__/doc_viewer_render_tab.test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Mounting and unmounting DocViewerRenderTab 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ +
    , + Object { + "hit": Object {}, + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": [MockFunction], + }, + ], +} +`; diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/__tests__/doc_viewer.js b/src/legacy/core_plugins/kibana/public/doc_viewer/__tests__/doc_viewer.js deleted file mode 100644 index bb31682cdda85..0000000000000 --- a/src/legacy/core_plugins/kibana/public/doc_viewer/__tests__/doc_viewer.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 angular from 'angular'; -import _ from 'lodash'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import 'ui/private'; - -import { DocViewsRegistryProvider } from 'ui/registry/doc_views'; -import { uiRegistry } from 'ui/registry/_registry'; - -describe('docViewer', function () { - let stubRegistry; - let $elem; - let init; - - beforeEach(function () { - ngMock.module('kibana', function (PrivateProvider) { - stubRegistry = uiRegistry({ - index: ['name'], - order: ['order'], - constructor() { - this.forEach(docView => { - docView.shouldShow = docView.shouldShow || _.constant(true); - docView.name = docView.name || docView.title; - }); - } - }); - - PrivateProvider.swap(DocViewsRegistryProvider, stubRegistry); - }); - - // Create the scope - ngMock.inject(function () {}); - }); - - beforeEach(function () { - $elem = angular.element(''); - init = function init() { - ngMock.inject(function ($rootScope, $compile) { - $compile($elem)($rootScope); - $elem.scope().$digest(); - return $elem; - }); - }; - - }); - - describe('injecting views', function () { - - function registerExtension(def = {}) { - stubRegistry.register(function () { - return _.defaults(def, { - title: 'exampleView', - order: 0, - directive: { - template: `Example` - } - }); - }); - } - it('should have a tab for the view', function () { - registerExtension(); - registerExtension({ title: 'exampleView2' }); - init(); - expect($elem.find('.euiTabs button').length).to.be(2); - }); - - it('should activate the first view in order', function () { - registerExtension({ order: 2 }); - registerExtension({ title: 'exampleView2' }); - init(); - expect($elem.find('.euiTabs .euiTab-isSelected').text().trim()).to.be('exampleView2'); - }); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/_doc_viewer.scss b/src/legacy/core_plugins/kibana/public/doc_viewer/_doc_viewer.scss index 539efbe592a51..25aa530976719 100644 --- a/src/legacy/core_plugins/kibana/public/doc_viewer/_doc_viewer.scss +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/_doc_viewer.scss @@ -1,3 +1,7 @@ +.kbnDocViewerTable { + margin-top: $euiSizeS; +} + .kbnDocViewer { pre, .kbnDocViewer__value { @@ -6,6 +10,11 @@ word-wrap: break-word; white-space: pre-wrap; color: $euiColorFullShade; + vertical-align: top; + padding-top: 2px; + } + .kbnDocViewer__field { + padding-top: 8px; } .dscFieldName { @@ -28,20 +37,22 @@ } } -.kbnDocViewer__content { - background-color: $euiColorEmptyShade; - padding: $euiSizeS 0 0 0; -} - .kbnDocViewer__buttons, .kbnDocViewer__field { white-space: nowrap; } +.kbnDocViewer__buttons { + width: 60px; +} + +.kbnDocViewer__field { + width: 160px; +} .kbnDocViewer__actionButton { opacity: 0; - - &:focus { - opacity: 1; - } } +.kbnDocViewer__warning { + margin-right: $euiSizeS; +} + diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.js b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.js deleted file mode 100644 index 060658b11400e..0000000000000 --- a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.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. - */ - -import $ from 'jquery'; -import { uiModules } from 'ui/modules'; -import { DocViewsRegistryProvider } from 'ui/registry/doc_views'; - -import 'ui/directives/render_directive'; - -uiModules.get('apps/discover') - .directive('docViewer', function (Private) { - const docViews = Private(DocViewsRegistryProvider); - return { - restrict: 'E', - scope: { - hit: '=', - indexPattern: '=', - filter: '=?', - columns: '=?', - onAddColumn: '=?', - onRemoveColumn: '=?', - }, - template: function ($el) { - const $viewer = $('
    '); - $el.append($viewer); - const $tabs = $('
    '); - const $content = $('
    '); - $viewer.append($tabs); - $viewer.append($content); - docViews.inOrder.forEach(view => { - const $tab = $( - `` - ); - $tabs.append($tab); - const $viewAttrs = ` - hit="hit" - index-pattern="indexPattern" - filter="filter" - columns="columns" - on-add-column="onAddColumn" - on-remove-column="onRemoveColumn" - `; - const $ext = $(` - `); - $ext.html(view.directive.template); - $content.append($ext); - }); - return $el.html(); - }, - controller: function ($scope) { - $scope.mode = docViews.inOrder[0].name; - $scope.docViews = docViews.byName; - } - }; - }); diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.test.tsx b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.test.tsx new file mode 100644 index 0000000000000..433dca65f428e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.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 React from 'react'; +import { mount, shallow } from 'enzyme'; +import { DocViewer } from './doc_viewer'; +// @ts-ignore +import { findTestSubject } from '@elastic/eui/lib/test'; +import { addDocView, emptyDocViews, DocViewRenderProps } from 'ui/registry/doc_views'; + +beforeEach(() => { + emptyDocViews(); +}); + +test('Render with 3 different tabs', () => { + addDocView({ order: 20, title: 'React component', component: () =>
    test
    }); + addDocView({ order: 10, title: 'Render function', render: jest.fn() }); + addDocView({ order: 30, title: 'Invalid doc view' }); + + const renderProps = { hit: {} } as DocViewRenderProps; + + const wrapper = shallow(); + + expect(wrapper).toMatchSnapshot(); +}); + +test('Render with 1 tab displaying error message', () => { + function SomeComponent() { + // this is just a placeholder + return null; + } + + addDocView({ + order: 10, + title: 'React component', + component: SomeComponent, + }); + + const renderProps = { hit: {} } as DocViewRenderProps; + const errorMsg = 'Catch me if you can!'; + + const wrapper = mount(); + const error = new Error(errorMsg); + wrapper.find(SomeComponent).simulateError(error); + const errorMsgComponent = findTestSubject(wrapper, 'docViewerError'); + expect(errorMsgComponent.text()).toMatch(new RegExp(`${errorMsg}`)); +}); diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.tsx b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.tsx new file mode 100644 index 0000000000000..671e652b60116 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer.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 { EuiTabbedContent } from '@elastic/eui'; +import { getDocViewsSorted, DocViewRenderProps } from 'ui/registry/doc_views'; +import { DocViewerTab } from './doc_viewer_tab'; + +/** + * Rendering tabs with different views of 1 Elasticsearch hit in Discover. + * The tabs are provided by the `docs_views` registry. + * A view can contain a React `component`, or any JS framework by using + * a `render` function. + */ +export function DocViewer(renderProps: DocViewRenderProps) { + const tabs = getDocViewsSorted(renderProps.hit).map(({ title, render, component }, idx) => { + return { + id: title, + name: title, + content: ( + + ), + }; + }); + + return ( +
    + +
    + ); +} diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_directive.ts b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_directive.ts new file mode 100644 index 0000000000000..202fca6ee7b52 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_directive.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. + */ + +// @ts-ignore +import { uiModules } from 'ui/modules'; +import { DocViewer } from './doc_viewer'; + +uiModules.get('apps/discover').directive('docViewer', (reactDirective: any) => { + return reactDirective(DocViewer, undefined, { + restrict: 'E', + scope: { + hit: '=', + indexPattern: '=', + filter: '=?', + columns: '=?', + onAddColumn: '=?', + onRemoveColumn: '=?', + }, + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_error.tsx b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_error.tsx new file mode 100644 index 0000000000000..b81610c5569a4 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_error.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 React from 'react'; +import { EuiCallOut, EuiCodeBlock } from '@elastic/eui'; +// @ts-ignore +import { formatMsg, formatStack } from '../../../../ui/public/notify/lib'; + +interface Props { + error: Error | string | null; +} + +export function DocViewerError({ error }: Props) { + const errMsg = formatMsg(error); + const errStack = error ? formatStack(error) : ''; + + return ( + + {errStack && {errStack}} + + ); +} diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_tab.test.tsx b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_tab.test.tsx new file mode 100644 index 0000000000000..3bb59a8dc958c --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_tab.test.tsx @@ -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 React from 'react'; +import { mount } from 'enzyme'; +import { DocViewRenderTab } from './doc_viewer_render_tab'; +import { DocViewRenderProps } from 'ui/registry/doc_views'; + +test('Mounting and unmounting DocViewerRenderTab', () => { + const unmountFn = jest.fn(); + const renderFn = jest.fn(() => unmountFn); + const renderProps = { + hit: {}, + }; + + const wrapper = mount( + + ); + + expect(renderFn).toMatchSnapshot(); + + wrapper.unmount(); + + expect(unmountFn).toBeCalled(); +}); diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_tab.tsx b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_tab.tsx new file mode 100644 index 0000000000000..185ff163dad2a --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_render_tab.tsx @@ -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 React, { useRef, useEffect } from 'react'; +import { DocViewRenderFn, DocViewRenderProps } from 'ui/registry/doc_views'; + +interface Props { + render: DocViewRenderFn; + renderProps: DocViewRenderProps; +} +/** + * Responsible for rendering a tab provided by a render function. + * So any other framework can be used (E.g. legacy Angular 3rd party plugin code) + * The provided `render` function is called with a reference to the + * component's `HTMLDivElement` as 1st arg and `renderProps` as 2nd arg + */ +export function DocViewRenderTab({ render, renderProps }: Props) { + const ref = useRef(null); + useEffect(() => { + if (ref && ref.current) { + return render(ref.current, renderProps); + } + }, [render, renderProps]); + return
    ; +} diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_tab.tsx b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_tab.tsx new file mode 100644 index 0000000000000..0b25421d8aff3 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/doc_viewer_tab.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 { I18nProvider } from '@kbn/i18n/react'; +import { DocViewRenderProps, DocViewRenderFn } from 'ui/registry/doc_views'; +import { DocViewRenderTab } from './doc_viewer_render_tab'; +import { DocViewerError } from './doc_viewer_render_error'; + +interface Props { + component?: React.ComponentType; + id: number; + render?: DocViewRenderFn; + renderProps: DocViewRenderProps; + title: string; +} + +interface State { + error: null | Error | string; + hasError: boolean; +} +/** + * Renders the tab content of a doc view. + * Displays an error message when it encounters exceptions, thanks to + * Error Boundaries. + */ +export class DocViewerTab extends React.Component { + state = { + hasError: false, + error: null, + }; + + static getDerivedStateFromError(error: unknown) { + // Update state so the next render will show the fallback UI. + return { hasError: true, error }; + } + + shouldComponentUpdate(nextProps: Props, nextState: State) { + return ( + nextProps.renderProps.hit._id !== this.props.renderProps.hit._id || + nextProps.id !== this.props.id || + nextState.hasError + ); + } + + render() { + const { component, render, renderProps, title } = this.props; + const { hasError, error } = this.state; + + if (hasError && error) { + return ; + } else if (!render && !component) { + return ( + + ); + } + + if (render) { + // doc view is provided by a render function, e.g. for legacy Angular code + return ; + } + + // doc view is provided by a react component + + const Component = component as any; + return ( + + + + ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/doc_viewer/index.js b/src/legacy/core_plugins/kibana/public/doc_viewer/index.js index 791a881fd17bc..0771de0f2d599 100644 --- a/src/legacy/core_plugins/kibana/public/doc_viewer/index.js +++ b/src/legacy/core_plugins/kibana/public/doc_viewer/index.js @@ -17,4 +17,4 @@ * under the License. */ -import './doc_viewer'; +import './doc_viewer_directive'; diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap index 2ef87889cb6c8..fde7aba8ac965 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap @@ -2,8 +2,6 @@ exports[`apmUiEnabled 1`] = ` @@ -54,12 +52,7 @@ exports[`apmUiEnabled 1`] = ` @@ -345,12 +321,7 @@ exports[`isNewKibanaInstance 1`] = ` @@ -594,12 +553,7 @@ exports[`mlEnabled 1`] = ` @@ -923,12 +860,7 @@ exports[`render 1`] = ` `; @@ -1168,8 +1090,6 @@ exports[`home welcome stores skip welcome setting if skipped 1`] = ` View data @@ -59,13 +55,8 @@ exports[`should render popover when appLinks is not empty 1`] = ` exports[`should render simple button when appLinks is empty 1`] = ` View data diff --git a/src/legacy/core_plugins/kibana/public/home/components/_welcome.scss b/src/legacy/core_plugins/kibana/public/home/components/_welcome.scss index 821fbe46b1404..d8c777534647b 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/_welcome.scss +++ b/src/legacy/core_plugins/kibana/public/home/components/_welcome.scss @@ -1,6 +1,5 @@ - .homWelcome { - @include kibanaFullScreenGraphics; + @include kibanaFullScreenGraphics($euiZLevel6); } .homWelcome__header { diff --git a/src/legacy/core_plugins/kibana/public/home/components/home.js b/src/legacy/core_plugins/kibana/public/home/components/home.js index 3b7e2c0990c6f..76f15f797ed6c 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/home.js +++ b/src/legacy/core_plugins/kibana/public/home/components/home.js @@ -225,6 +225,10 @@ export class Home extends Component { ); } @@ -247,6 +251,10 @@ export class Home extends Component { Home.propTypes = { addBasePath: PropTypes.func.isRequired, + fetchTelemetry: PropTypes.func.isRequired, + getTelemetryBannerId: PropTypes.func.isRequired, + setOptIn: PropTypes.func.isRequired, + shouldShowTelemetryOptIn: PropTypes.bool.isRequired, directories: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.string.isRequired, diff --git a/src/legacy/core_plugins/kibana/public/home/components/home.test.js b/src/legacy/core_plugins/kibana/public/home/components/home.test.js index c10aa3f0b1e32..aa520ba2ed5f9 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/home.test.js +++ b/src/legacy/core_plugins/kibana/public/home/components/home.test.js @@ -17,30 +17,14 @@ * under the License. */ +import './home.test.mocks'; + import React from 'react'; import sinon from 'sinon'; import { shallow } from 'enzyme'; import { Home } from './home'; import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; -jest.mock( - 'ui/chrome', - () => ({ - getBasePath: jest.fn(() => 'path'), - getInjected: jest.fn(() => ''), - }), - { virtual: true } -); - -jest.mock( - 'ui/capabilities', - () => ({ - catalogue: {}, - management: {}, - navLinks: {} - }) -); - describe('home', () => { let defaultProps; @@ -50,6 +34,10 @@ describe('home', () => { apmUiEnabled: true, mlEnabled: true, kibanaVersion: '99.2.1', + fetchTelemetry: jest.fn(), + getTelemetryBannerId: jest.fn(), + setOptIn: jest.fn(), + showTelemetryOptIn: false, addBasePath(url) { return `base_path/${url}`; }, diff --git a/src/legacy/core_plugins/kibana/public/home/components/home.test.mocks.ts b/src/legacy/core_plugins/kibana/public/home/components/home.test.mocks.ts new file mode 100644 index 0000000000000..1eed597a90a4b --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/components/home.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. + */ + +import { notificationServiceMock } from '../../../../../../core/public/mocks'; + +jest.doMock('ui/new_platform', () => { + return { + npSetup: { + core: { + notifications: notificationServiceMock.createSetupContract(), + }, + }, + }; +}); + +jest.doMock( + 'ui/chrome', + () => ({ + getBasePath: jest.fn(() => 'path'), + getInjected: jest.fn(() => ''), + }), + { virtual: true } +); + +jest.doMock('ui/capabilities', () => ({ + catalogue: {}, + management: {}, + navLinks: {}, +})); diff --git a/src/legacy/core_plugins/kibana/public/home/components/home_app.js b/src/legacy/core_plugins/kibana/public/home/components/home_app.js index fc24eeaa0f451..9aa44863f6d70 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/home_app.js +++ b/src/legacy/core_plugins/kibana/public/home/components/home_app.js @@ -30,12 +30,10 @@ import { } from 'react-router-dom'; import { getTutorial } from '../load_tutorials'; import { replaceTemplateStrings } from './tutorial/replace_template_strings'; +import { telemetryOptInProvider, shouldShowTelemetryOptIn } from '../kibana_services'; import chrome from 'ui/chrome'; -export function HomeApp({ - directories, -}) { - +export function HomeApp({ directories }) { const isCloudEnabled = chrome.getInjected('isCloudEnabled', false); const apmUiEnabled = chrome.getInjected('apmUiEnabled', true); const mlEnabled = chrome.getInjected('mlEnabled', false); @@ -94,6 +92,10 @@ export function HomeApp({ find={savedObjectsClient.find} localStorage={localStorage} urlBasePath={chrome.getBasePath()} + shouldShowTelemetryOptIn={shouldShowTelemetryOptIn} + setOptIn={telemetryOptInProvider.setOptIn} + fetchTelemetry={telemetryOptInProvider.fetchExample} + getTelemetryBannerId={telemetryOptInProvider.getBannerId} /> diff --git a/src/legacy/core_plugins/kibana/public/home/components/sample_data/index.tsx b/src/legacy/core_plugins/kibana/public/home/components/sample_data/index.tsx new file mode 100644 index 0000000000000..1bb8bd214d2cb --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/components/sample_data/index.tsx @@ -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. + */ + +/* + * The UI and related logic for the welcome screen that *should* show only + * when it is enabled (the default) and there is no Kibana-consumed data + * in Elasticsearch. + */ + +import React from 'react'; +import { + // @ts-ignore + EuiCard, + EuiButton, + EuiButtonEmpty, +} from '@elastic/eui'; + +import { FormattedMessage } from '@kbn/i18n/react'; + +interface Props { + urlBasePath: string; + onDecline: () => void; + onConfirm: () => void; +} + +export function SampleDataCard({ urlBasePath, onDecline, onConfirm }: Props) { + return ( + } + description={ + + } + footer={ +
    + + + + + + +
    + } + /> + ); +} diff --git a/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/index.ts b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/index.ts new file mode 100644 index 0000000000000..63636433bc00b --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/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. + */ +import { renderTelemetryOptInCard, Props } from './telemetry_opt_in_card'; + +export const TelemetryOptInCard = (props: Props) => { + return renderTelemetryOptInCard(props); +}; diff --git a/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/opt_in_details_component.tsx b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/opt_in_details_component.tsx new file mode 100644 index 0000000000000..d90f54b2bcb54 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/opt_in_details_component.tsx @@ -0,0 +1,163 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { + fetchTelemetry: () => Promise; + onClose: () => void; +} + +interface State { + isLoading: boolean; + hasPrivilegeToRead: boolean; + data: any[] | null; +} + +/** + * React component for displaying the example data associated with the Telemetry opt-in banner. + */ +export class OptInExampleFlyout extends React.PureComponent { + public readonly state: State = { + data: null, + isLoading: true, + hasPrivilegeToRead: false, + }; + + componentDidMount() { + this.props + .fetchTelemetry() + .then(response => + this.setState({ + data: Array.isArray(response.data) ? response.data : null, + isLoading: false, + hasPrivilegeToRead: true, + }) + ) + .catch(err => { + this.setState({ + isLoading: false, + hasPrivilegeToRead: err.status !== 403, + }); + }); + } + + renderBody({ data, isLoading, hasPrivilegeToRead }: State) { + if (isLoading) { + return ( + + + + + + ); + } + + if (!hasPrivilegeToRead) { + return ( + + } + color="danger" + iconType="cross" + > + + + ); + } + + if (data === null) { + return ( + + } + color="danger" + iconType="cross" + > + + + ); + } + + return {JSON.stringify(data, null, 2)}; + } + + render() { + return ( + + + + +

    + +

    +
    + + + + + +
    + {this.renderBody(this.state)} +
    +
    + ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/opt_in_message.tsx b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/opt_in_message.tsx new file mode 100644 index 0000000000000..0f581e819b052 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/opt_in_message.tsx @@ -0,0 +1,106 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { OptInExampleFlyout } from './opt_in_details_component'; + +interface Props { + fetchTelemetry: () => Promise; +} + +interface State { + showDetails: boolean; + showExample: boolean; +} + +export class OptInMessage extends React.PureComponent { + public readonly state: State = { + showDetails: false, + showExample: false, + }; + + toggleShowExample = () => { + this.setState(prevState => ({ + showExample: !prevState.showExample, + })); + }; + + render() { + const { fetchTelemetry } = this.props; + const { showDetails, showExample } = this.state; + + const getDetails = () => ( + + + + ), + telemetryPrivacyStatementLink: ( + + + + ), + }} + /> + ); + + const getFlyoutDetails = () => ( + this.setState({ showExample: false })} + fetchTelemetry={fetchTelemetry} + /> + ); + + const getReadMore = () => ( + this.setState({ showDetails: true })}> + + + ); + + return ( + + {' '} + {!showDetails && getReadMore()} + {showDetails && getDetails()} + {showDetails && showExample && getFlyoutDetails()} + + ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/telemetry_opt_in_card.tsx b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/telemetry_opt_in_card.tsx new file mode 100644 index 0000000000000..5fa842291b028 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/components/telemetry_opt_in/telemetry_opt_in_card.tsx @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { FormattedMessage } from '@kbn/i18n/react'; +import { + // @ts-ignore + EuiCard, + EuiButton, +} from '@elastic/eui'; +import { OptInMessage } from './opt_in_message'; + +export interface Props { + urlBasePath: string; + onConfirm: () => void; + onDecline: () => void; + fetchTelemetry: () => Promise; +} + +export function renderTelemetryOptInCard({ + urlBasePath, + fetchTelemetry, + onConfirm, + onDecline, +}: Props) { + return ( + + } + description={} + footer={ +
    + + + + + + +
    + } + /> + ); +} diff --git a/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/footer.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/footer.test.js.snap index 7d4cba8a2d5a7..9fd3eebe96d8c 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/footer.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/footer.test.js.snap @@ -24,12 +24,8 @@ exports[`render 1`] = ` grow={false} > launch myapp diff --git a/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/instruction_set.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/instruction_set.test.js.snap index 9b50b31448ecc..48685057317f9 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/instruction_set.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/instruction_set.test.js.snap @@ -28,7 +28,6 @@ exports[`render 1`] = ` size="m" > - @@ -177,18 +171,13 @@ exports[`statusCheckState checking status 1`] = ` grow={false} > custom btn label
    -
    + @@ -231,7 +220,6 @@ exports[`statusCheckState failed status check - error 1`] = ` size="m" > - @@ -296,18 +282,13 @@ exports[`statusCheckState failed status check - error 1`] = ` grow={false} > custom btn label
    -
    + @@ -355,7 +336,6 @@ exports[`statusCheckState failed status check - no data 1`] = ` size="m" > - @@ -420,18 +398,13 @@ exports[`statusCheckState failed status check - no data 1`] = ` grow={false} > custom btn label - + @@ -479,7 +452,6 @@ exports[`statusCheckState initial state - no check has been attempted 1`] = ` size="m" > - @@ -544,18 +514,13 @@ exports[`statusCheckState initial state - no check has been attempted 1`] = ` grow={false} > custom btn label - + @@ -598,7 +563,6 @@ exports[`statusCheckState successful status check 1`] = ` size="m" > - @@ -663,18 +625,13 @@ exports[`statusCheckState successful status check 1`] = ` grow={false} > custom btn label - + diff --git a/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/introduction.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/introduction.test.js.snap index bc64579a4d71b..918bcbf7415e8 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/introduction.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/home/components/tutorial/__snapshots__/introduction.test.js.snap @@ -26,14 +26,9 @@ exports[`props exportedFieldsUrl 1`] = `
    - @@ -137,19 +135,14 @@ exports[`bulkCreate should display error message when bulkCreate request fails 1 grow={false} > Load Kibana objects - + @@ -180,39 +173,42 @@ exports[`bulkCreate should display error message when bulkCreate request fails 1
    - - + - - Incomplete Step - -   - - - -
    - - -

    + + + - Load Kibana objects -

    -
    +

    + Load Kibana objects +

    + +
    @@ -245,14 +241,9 @@ exports[`bulkCreate should display error message when bulkCreate request fails 1 className="euiFlexItem euiFlexItem--flexGrowZero" >
    @@ -590,14 +577,9 @@ exports[`bulkCreate should display success message when bulkCreate is successful className="euiFlexItem euiFlexItem--flexGrowZero" >
    { + return { + Markdown: () =>
    , + }; +}); + + test('should render content with markdown', () => { const component = shallow( { + return { + Markdown: () =>
    , + }; +}); + test('render', () => { const component = shallowWithIntl( { + return { + Markdown: () =>
    , + }; +}); + test('render', () => { const component = shallowWithIntl( { + return { + Markdown: () =>
    , + }; +}); + function buildInstructionSet(type) { return { instructionSets: [ diff --git a/src/legacy/core_plugins/kibana/public/home/components/welcome.js b/src/legacy/core_plugins/kibana/public/home/components/welcome.js deleted file mode 100644 index 98560b748ec0d..0000000000000 --- a/src/legacy/core_plugins/kibana/public/home/components/welcome.js +++ /dev/null @@ -1,130 +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. - */ - -/* - * The UI and related logic for the welcome screen that *should* show only - * when it is enabled (the default) and there is no Kibana-consumed data - * in Elasticsearch. - */ - -import React from 'react'; -import PropTypes from 'prop-types'; -import { - EuiCard, - EuiTitle, - EuiSpacer, - EuiFlexGroup, - EuiFlexItem, - EuiText, - EuiIcon, - EuiButton, - EuiButtonEmpty, - EuiPortal, -} from '@elastic/eui'; - -import { FormattedMessage } from '@kbn/i18n/react'; - -/** - * Shows a full-screen welcome page that gives helpful quick links to beginners. - */ -export class Welcome extends React.Component { - hideOnEsc = e => { - if (e.key === 'Escape') { - this.props.onSkip(); - } - }; - - componentDidMount() { - document.addEventListener('keydown', this.hideOnEsc); - } - - componentWillUnmount() { - document.removeEventListener('keydown', this.hideOnEsc); - } - - render() { - const { urlBasePath, onSkip } = this.props; - - return ( - -
    -
    -
    - - - - - -

    - -

    -
    - -

    - -

    -
    - -
    -
    -
    - - - } - description={ - } - footer={ -
    - - - - - - -
    - } - /> -
    -
    -
    -
    -
    - ); - } -} - -Welcome.propTypes = { - urlBasePath: PropTypes.string.isRequired, - onSkip: PropTypes.func.isRequired, -}; diff --git a/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx b/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx new file mode 100644 index 0000000000000..8869819290263 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx @@ -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. + */ + +/* + * The UI and related logic for the welcome screen that *should* show only + * when it is enabled (the default) and there is no Kibana-consumed data + * in Elasticsearch. + */ + +import React from 'react'; +import { + EuiTitle, + EuiSpacer, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiIcon, + EuiPortal, +} from '@elastic/eui'; +// @ts-ignore +import { banners } from 'ui/notify'; + +import { FormattedMessage } from '@kbn/i18n/react'; +import chrome from 'ui/chrome'; +import { SampleDataCard } from './sample_data'; +import { TelemetryOptInCard } from './telemetry_opt_in'; +// @ts-ignore +import { trackUiMetric, METRIC_TYPE } from '../kibana_services'; + +interface Props { + urlBasePath: string; + onSkip: () => {}; + fetchTelemetry: () => Promise; + setOptIn: (enabled: boolean) => Promise; + getTelemetryBannerId: () => string; + shouldShowTelemetryOptIn: boolean; +} +interface State { + step: number; +} + +/** + * Shows a full-screen welcome page that gives helpful quick links to beginners. + */ +export class Welcome extends React.PureComponent { + public readonly state: State = { + step: 0, + }; + + private hideOnEsc = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + this.props.onSkip(); + } + }; + + private redirecToSampleData() { + const path = chrome.addBasePath('#/home/tutorial_directory/sampleData'); + window.location.href = path; + } + private async handleTelemetrySelection(confirm: boolean) { + const metricName = `telemetryOptIn${confirm ? 'Confirm' : 'Decline'}`; + trackUiMetric(METRIC_TYPE.CLICK, metricName); + await this.props.setOptIn(confirm); + const bannerId = this.props.getTelemetryBannerId(); + banners.remove(bannerId); + this.setState(() => ({ step: 1 })); + } + + private onSampleDataDecline = () => { + trackUiMetric(METRIC_TYPE.CLICK, 'sampleDataDecline'); + this.props.onSkip(); + }; + private onSampleDataConfirm = () => { + trackUiMetric(METRIC_TYPE.CLICK, 'sampleDataConfirm'); + this.redirecToSampleData(); + }; + + componentDidMount() { + trackUiMetric(METRIC_TYPE.LOADED, 'welcomeScreenMount'); + if (this.props.shouldShowTelemetryOptIn) { + trackUiMetric(METRIC_TYPE.COUNT, 'welcomeScreenWithTelemetryOptIn'); + } + document.addEventListener('keydown', this.hideOnEsc); + } + + componentWillUnmount() { + document.removeEventListener('keydown', this.hideOnEsc); + } + + render() { + const { urlBasePath, shouldShowTelemetryOptIn, fetchTelemetry } = this.props; + const { step } = this.state; + + return ( + +
    +
    +
    + + + + + +

    + +

    +
    + +

    + +

    +
    + +
    +
    +
    + + + {shouldShowTelemetryOptIn && step === 0 && ( + + )} + {(!shouldShowTelemetryOptIn || step === 1) && ( + + )} + + + +
    +
    +
    + ); + } +} diff --git a/src/legacy/core_plugins/kibana/public/home/kibana_services.js b/src/legacy/core_plugins/kibana/public/home/kibana_services.js index fc06a61ae343d..c5480e16491a9 100644 --- a/src/legacy/core_plugins/kibana/public/home/kibana_services.js +++ b/src/legacy/core_plugins/kibana/public/home/kibana_services.js @@ -18,9 +18,23 @@ */ import { uiModules } from 'ui/modules'; +import { npStart } from 'ui/new_platform'; +import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public'; +import { TelemetryOptInProvider } from './telemetry_opt_in'; export let indexPatternService; +export let shouldShowTelemetryOptIn; +export let telemetryOptInProvider; + +export const trackUiMetric = createUiStatsReporter('Kibana_home'); +export { METRIC_TYPE }; uiModules.get('kibana').run(($injector) => { + const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled'); + const telemetryBanner = npStart.core.injectedMetadata.getInjectedVar('telemetryBanner'); + const Private = $injector.get('Private'); + + telemetryOptInProvider = Private(TelemetryOptInProvider); + shouldShowTelemetryOptIn = telemetryEnabled && telemetryBanner && !telemetryOptInProvider.getOptIn(); indexPatternService = $injector.get('indexPatterns'); }); diff --git a/src/legacy/core_plugins/kibana/public/home/telemetry_opt_in.js b/src/legacy/core_plugins/kibana/public/home/telemetry_opt_in.js new file mode 100644 index 0000000000000..274820844da45 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/telemetry_opt_in.js @@ -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 moment from 'moment'; +import { setCanTrackUiMetrics } from 'ui/ui_metric'; +import { toastNotifications } from 'ui/notify'; +import { npStart } from 'ui/new_platform'; +import { i18n } from '@kbn/i18n'; + +export function TelemetryOptInProvider($injector, chrome) { + let currentOptInStatus = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn'); + let bannerId = null; + + setCanTrackUiMetrics(currentOptInStatus); + const provider = { + getBannerId: () => bannerId, + getOptIn: () => currentOptInStatus, + setBannerId(id) { bannerId = id; }, + setOptIn: async (enabled) => { + setCanTrackUiMetrics(enabled); + const $http = $injector.get('$http'); + + try { + await $http.post(chrome.addBasePath('/api/telemetry/v2/optIn'), { enabled }); + currentOptInStatus = enabled; + } catch (error) { + toastNotifications.addError(error, { + title: i18n.translate('kbn.home.telemetry.optInErrorToastTitle', { + defaultMessage: 'Error', + }), + toastMessage: i18n.translate('kbn.home.telemetry.optInErrorToastText', { + defaultMessage: 'An error occured while trying to set the usage statistics preference.', + }), + }); + return false; + } + + return true; + }, + fetchExample: async () => { + const $http = $injector.get('$http'); + return $http.post(chrome.addBasePath(`/api/telemetry/v2/clusters/_stats`), { + unencrypted: true, + timeRange: { + min: moment().subtract(20, 'minutes').toISOString(), + max: moment().toISOString() + } + }); + } + }; + + return provider; +} diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss index cdf292a64e595..c8a66f6c3913b 100644 --- a/src/legacy/core_plugins/kibana/public/index.scss +++ b/src/legacy/core_plugins/kibana/public/index.scss @@ -30,3 +30,10 @@ // Dashboard styles // MUST STAY AT THE BOTTOM BECAUSE OF DARK THEME IMPORTS @import './dashboard/index'; + +// helper class that hides elements when rendered in percy +@media only percy { + .hideInPercy { + visibility: hidden; + } +} diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index b6d4ec233e108..b11d0cac35b23 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -27,8 +27,7 @@ import { uiModules } from 'ui/modules'; // import the uiExports that we want to "use" import 'uiExports/home'; import 'uiExports/visTypes'; -import 'uiExports/visResponseHandlers'; -import 'uiExports/visRequestHandlers'; + import 'uiExports/visEditorTypes'; import 'uiExports/visualize'; import 'uiExports/savedObjectTypes'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/__jest__/__snapshots__/empty_state.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/__jest__/__snapshots__/empty_state.test.js.snap index af5e95b2ffcd9..5f366f4203c01 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/__jest__/__snapshots__/empty_state.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/empty_state/__jest__/__snapshots__/empty_state.test.js.snap @@ -57,12 +57,8 @@ exports[`EmptyState should render normally 1`] = ` - + - + kibana - + - + es - + @@ -75,7 +41,6 @@ exports[`IndicesList should change pages 1`] = ` iconType="arrowDown" onClick={[Function]} size="s" - type="button" > 5 , 10 , 20 , 50 , @@ -144,33 +101,15 @@ exports[`IndicesList should change pages 1`] = ` exports[`IndicesList should change per page 1`] = `
    - + - + kibana - + @@ -193,7 +132,6 @@ exports[`IndicesList should change per page 1`] = ` iconType="arrowDown" onClick={[Function]} size="s" - type="button" > 5 , 10 , 20 , 50 , @@ -271,22 +201,12 @@ exports[`IndicesList should change per page 1`] = ` exports[`IndicesList should highlight the query in the matches 1`] = `
    - + - + ki @@ -294,39 +214,15 @@ exports[`IndicesList should highlight the query in the matches 1`] = ` bana - + - + es - + @@ -349,7 +245,6 @@ exports[`IndicesList should highlight the query in the matches 1`] = ` iconType="arrowDown" onClick={[Function]} size="s" - type="button" > 5 , 10 , 20 , 50 , @@ -418,57 +305,23 @@ exports[`IndicesList should highlight the query in the matches 1`] = ` exports[`IndicesList should render normally 1`] = `
    - + - + kibana - + - + es - + @@ -491,7 +344,6 @@ exports[`IndicesList should render normally 1`] = ` iconType="arrowDown" onClick={[Function]} size="s" - type="button" > 5 , 10 , 20 , 50 , @@ -560,249 +404,87 @@ exports[`IndicesList should render normally 1`] = ` exports[`IndicesList updating props should render all new indices 1`] = `
    - + - + kibana - + - + es - + - + kibana - + - + es - + - + kibana - + - + es - + - + kibana - + - + es - + - + kibana - + - + es - + @@ -825,7 +507,6 @@ exports[`IndicesList updating props should render all new indices 1`] = ` iconType="arrowDown" onClick={[Function]} size="s" - type="button" > 5 , 10 , 20 , 50 , diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/__jest__/__snapshots__/step_time_field.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/__jest__/__snapshots__/step_time_field.test.js.snap index 3f25b180c9e1c..57910f2ec8aac 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/__jest__/__snapshots__/step_time_field.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/__jest__/__snapshots__/step_time_field.test.js.snap @@ -18,8 +18,6 @@ exports[`StepTimeField should enable the action button if the user decides to no exports[`StepTimeField should render "Custom index pattern ID already exists" when error is "Conflict" 1`] = `
    + @@ -117,8 +111,6 @@ exports[`StepTimeField should render a loading state when creating the index pat exports[`StepTimeField should render a selected timeField 1`] = `
    } label={ - - + } labelType="label" > @@ -98,7 +98,7 @@ exports[`TimeField should render a selected time field 1`] = `
    } label={ - - + } labelType="label" > @@ -182,7 +182,7 @@ exports[`TimeField should render normally 1`] = `
    } label={ - - + } labelType="label" > diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js index 4476ad868cbcf..37591d484d201 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_time_field/step_time_field.js @@ -89,7 +89,7 @@ export class StepTimeFieldComponent extends Component { this.setState({ isFetchingTimeFields: true }); const fields = await ensureMinimumTime( - indexPattern.fieldsFetcher.fetch(getFetchForWildcardOptions()) + indexPattern.fieldsFetcher.fetchForWildcard(pattern, getFetchForWildcardOptions()) ); const timeFields = extractTimeFields(fields); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js index b72a28d6f721c..f1294d6587e5b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js @@ -17,7 +17,9 @@ * under the License. */ -import { Field } from 'ui/index_patterns'; +import { setup as data } from '../../../../../../../data/public/legacy'; +const { FieldImpl: Field } = data.indexPatterns.__LEGACY; + import { RegistryFieldFormatEditorsProvider } from 'ui/registry/field_format_editors'; import { docTitle } from 'ui/doc_title'; import { KbnUrlProvider } from 'ui/url'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/__snapshots__/header.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/__snapshots__/header.test.js.snap index b3a9d78dc9de1..2e694b6363117 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/__snapshots__/header.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/__snapshots__/header.test.js.snap @@ -30,13 +30,8 @@ exports[`Header should render normally 1`] = ` grow={false} >
    `; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap index f9b79266d4253..0dc3ef2f44ea8 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap @@ -165,10 +165,7 @@ exports[`ObjectsTable export should allow the user to choose when exporting all grow={false} > { }, obj: { searchSource: { - getOwnField: () => 'MyIndexPattern*', + getOwnField: (field) => { + if(field === 'index') { return 'MyIndexPattern*';} + if(field === 'filter') { return [{ meta: { index: 'filterIndex' } }];} + }, }, + _serialize: () => { return { references: [{ id: 'MyIndexPattern*' }, { id: 'filterIndex' }] };}, }, }, ]; @@ -477,7 +481,17 @@ describe('Flyout', () => { type: 'index-pattern', }, ], - }, + }, { + 'existingIndexPatternId': 'filterIndex', + 'list': [ + { + 'id': 'filterIndex', + 'title': 'MyIndexPattern*', + 'type': 'index-pattern', + }, + ], + 'newIndexPatternId': undefined, + } ], }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js index 1bdf6dede4dee..625a32485de0f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js @@ -19,7 +19,7 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; -import { groupBy, take, get as getField } from 'lodash'; +import { take, get as getField } from 'lodash'; import { EuiFlyout, EuiFlyoutBody, @@ -50,9 +50,9 @@ import { importLegacyFile, resolveImportErrors, logLegacyImport, - processImportResponse, getDefaultTitle, } from '../../../../lib'; +import { processImportResponse } from '../../../../lib/process_import_response'; import { resolveSavedObjects, resolveSavedSearches, @@ -273,9 +273,15 @@ class FlyoutUI extends Component { confirmModalPromise ); - const byId = groupBy(conflictedIndexPatterns, ({ obj }) => - obj.searchSource.getOwnField('index') - ); + const byId = {}; + conflictedIndexPatterns + .map(({ doc, obj }) => { + return { doc, obj: obj._serialize() }; + }).forEach(({ doc, obj }) => + obj.references.forEach(ref => { + byId[ref.id] = byId[ref.id] != null ? byId[ref.id].concat({ doc, obj }) : [{ doc, obj }]; + }) + ); const unmatchedReferences = Object.entries(byId).reduce( (accum, [existingIndexPatternId, list]) => { accum.push({ diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap index e51c8d9f9c7a2..51bd51a5e2e58 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap @@ -31,13 +31,10 @@ exports[`Header should render normally 1`] = ` grow={false} > { @@ -238,6 +245,24 @@ class TableUI extends PureComponent { icon: 'kqlSelector', onClick: object => onShowRelationships(object), }, + ...this.extraActions.map(action => { + return { + ...action.euiAction, + onClick: (object) => { + this.setState({ + activeAction: action + }); + + action.registerOnFinishCallback(() => { + this.setState({ + activeAction: null, + }); + }); + + action.euiAction.onClick(object); + } + }; + }) ], }, ]; @@ -269,8 +294,11 @@ class TableUI extends PureComponent { ); + const activeActionContents = this.state.activeAction ? this.state.activeAction.render() : null; + return ( + {activeActionContents} { { obj: { searchSource: { - getOwnField: () => '1', + getOwnField: (field) => { + return field === 'index' ? '1' : undefined; + }, }, hydrateIndexPattern, save, @@ -247,7 +249,9 @@ describe('resolveSavedObjects', () => { { obj: { searchSource: { - getOwnField: () => '3', + getOwnField: (field) => { + return field === 'index' ? '3' : undefined; + }, }, hydrateIndexPattern, save, @@ -283,6 +287,63 @@ describe('resolveSavedObjects', () => { expect(hydrateIndexPattern).toHaveBeenCalledWith('2'); expect(hydrateIndexPattern).toHaveBeenCalledWith('4'); }); + + it('should resolve filter index conflicts', async () => { + const hydrateIndexPattern = jest.fn(); + const save = jest.fn(); + + const conflictedIndexPatterns = [ + { + obj: { + searchSource: { + getOwnField: (field) => { + return field === 'index' ? '1' : [{ meta: { index: 'filterIndex' } }]; + }, + setField: jest.fn(), + }, + hydrateIndexPattern, + save, + }, + }, + { + obj: { + searchSource: { + getOwnField: (field) => { + return field === 'index' ? '3' : undefined; + }, + }, + hydrateIndexPattern, + save, + }, + }, + ]; + + const resolutions = [ + { + oldId: '1', + newId: '2', + }, + { + oldId: '3', + newId: '4', + }, + { + oldId: 'filterIndex', + newId: 'newFilterIndex', + }, + ]; + + const overwriteAll = false; + + await resolveIndexPatternConflicts( + resolutions, + conflictedIndexPatterns, + overwriteAll + ); + + expect(conflictedIndexPatterns[0].obj.searchSource.setField).toHaveBeenCalledWith('filter', [{ meta: { index: 'newFilterIndex' } }]); + expect(save.mock.calls.length).toBe(2); + }); }); describe('saveObjects', () => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.js deleted file mode 100644 index 51ed2062818cc..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.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. - */ - -export function processImportResponse(response) { - // Go through the failures and split between unmatchedReferences and failedImports - const failedImports = []; - const unmatchedReferences = new Map(); - for (const { error, ...obj } of response.errors || []) { - failedImports.push({ obj, error }); - if (error.type !== 'missing_references') { - continue; - } - // Currently only supports resolving references on index patterns - const indexPatternRefs = error.references.filter(ref => ref.type === 'index-pattern'); - for (const missingReference of indexPatternRefs) { - const conflict = unmatchedReferences.get(`${missingReference.type}:${missingReference.id}`) || { - existingIndexPatternId: missingReference.id, - list: [], - newIndexPatternId: undefined, - }; - conflict.list.push(obj); - unmatchedReferences.set(`${missingReference.type}:${missingReference.id}`, conflict); - } - } - - return { - failedImports, - unmatchedReferences: Array.from(unmatchedReferences.values()), - // Import won't be successful in the scenario unmatched references exist, import API returned errors of type unknown or import API - // returned errors of type missing_references. - status: unmatchedReferences.size === 0 && !failedImports.some(issue => issue.error.type === 'conflict') - ? 'success' - : 'idle', - importCount: response.successCount, - conflictedSavedObjectsLinkedToSavedSearches: undefined, - conflictedSearchDocs: undefined, - }; -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts new file mode 100644 index 0000000000000..029cb620b52c7 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts @@ -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 { + SavedObjectsImportResponse, + SavedObjectsImportConflictError, + SavedObjectsImportUnsupportedTypeError, + SavedObjectsImportMissingReferencesError, + SavedObjectsImportUnknownError, + SavedObjectsImportError, +} from 'src/core/server'; + +export interface ProcessedImportResponse { + failedImports: Array<{ + obj: Pick; + error: + | SavedObjectsImportConflictError + | SavedObjectsImportUnsupportedTypeError + | SavedObjectsImportMissingReferencesError + | SavedObjectsImportUnknownError; + }>; + unmatchedReferences: Array<{ + existingIndexPatternId: string; + list: Array>; + newIndexPatternId: string | undefined; + }>; + status: 'success' | 'idle'; + importCount: number; + conflictedSavedObjectsLinkedToSavedSearches: undefined; + conflictedSearchDocs: undefined; +} + +export function processImportResponse( + response: SavedObjectsImportResponse +): ProcessedImportResponse { + // Go through the failures and split between unmatchedReferences and failedImports + const failedImports = []; + const unmatchedReferences = new Map(); + for (const { error, ...obj } of response.errors || []) { + failedImports.push({ obj, error }); + if (error.type !== 'missing_references') { + continue; + } + // Currently only supports resolving references on index patterns + const indexPatternRefs = error.references.filter(ref => ref.type === 'index-pattern'); + for (const missingReference of indexPatternRefs) { + const conflict = unmatchedReferences.get( + `${missingReference.type}:${missingReference.id}` + ) || { + existingIndexPatternId: missingReference.id, + list: [], + newIndexPatternId: undefined, + }; + conflict.list.push(obj); + unmatchedReferences.set(`${missingReference.type}:${missingReference.id}`, conflict); + } + } + + return { + failedImports, + unmatchedReferences: Array.from(unmatchedReferences.values()), + // Import won't be successful in the scenario unmatched references exist, import API returned errors of type unknown or import API + // returned errors of type missing_references. + status: + unmatchedReferences.size === 0 && + !failedImports.some(issue => issue.error.type === 'conflict') + ? 'success' + : 'idle', + importCount: response.successCount, + conflictedSavedObjectsLinkedToSavedSearches: undefined, + conflictedSearchDocs: undefined, + }; +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js index 1468b3d90400d..eeb5fb778b707 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js @@ -140,19 +140,38 @@ export async function resolveIndexPatternConflicts( overwriteAll ) { let importCount = 0; + await awaitEachItemInParallel(conflictedIndexPatterns, async ({ obj }) => { + // Resolve search index reference: let oldIndexId = obj.searchSource.getOwnField('index'); // Depending on the object, this can either be the raw id or the actual index pattern object if (typeof oldIndexId !== 'string') { oldIndexId = oldIndexId.id; } - const resolution = resolutions.find(({ oldId }) => oldId === oldIndexId); + let resolution = resolutions.find(({ oldId }) => oldId === oldIndexId); + if (resolution) { + const newIndexId = resolution.newId; + await obj.hydrateIndexPattern(newIndexId); + } + + // Resolve filter index reference: + const filter = (obj.searchSource.getOwnField('filter') || []).map((filter) => { + if (!(filter.meta && filter.meta.index)) { + return filter; + } + + resolution = resolutions.find(({ oldId }) => oldId === filter.meta.index); + return resolution ? ({ ...filter, ...{ meta: { ...filter.meta, index: resolution.newId } } }) : filter; + }); + + if (filter.length > 0) { + obj.searchSource.setField('filter', filter); + } + if (!resolution) { // The user decided to skip this conflict so do nothing return; } - const newIndexId = resolution.newId; - await obj.hydrateIndexPattern(newIndexId); if (await saveObject(obj, overwriteAll)) { importCount++; } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap index 0fa95c561001f..eae7a69a74a4f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap @@ -5,8 +5,6 @@ exports[`Form should not render no settings message when instructed not to 1`] = exports[`Form should render no settings message when there are no settings 1`] = ` @@ -96,8 +92,6 @@ exports[`Form should render normally 1`] = ` size="l" /> @@ -139,8 +133,6 @@ exports[`Form should render normally 1`] = ` size="l" /> @@ -216,8 +208,6 @@ exports[`Form should render normally 1`] = ` exports[`Form should render read-only when saving is disabled 1`] = ` @@ -277,8 +267,6 @@ exports[`Form should render read-only when saving is disabled 1`] = ` size="l" /> @@ -320,8 +308,6 @@ exports[`Form should render read-only when saving is disabled 1`] = ` size="l" /> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js index 5dc9d8d4ee737..0155b10f60218 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js @@ -45,6 +45,9 @@ const names = { search: i18n.translate('kbn.management.settings.categoryNames.searchLabel', { defaultMessage: 'Search', }), + siem: i18n.translate('kbn.management.settings.categoryNames.siemLabel', { + defaultMessage: 'SIEM', + }), }; export function getCategoryName(category) { diff --git a/src/legacy/core_plugins/kibana/public/table_list_view/table_list_view.js b/src/legacy/core_plugins/kibana/public/table_list_view/table_list_view.js index 97bacb45d7ad8..df4634b75373e 100644 --- a/src/legacy/core_plugins/kibana/public/table_list_view/table_list_view.js +++ b/src/legacy/core_plugins/kibana/public/table_list_view/table_list_view.js @@ -39,8 +39,9 @@ import { EuiCallOut, } from '@elastic/eui'; +import { npStart } from 'ui/new_platform'; + export const EMPTY_FILTER = ''; -const PAGE_SIZE_OPTIONS = [10, 20, 50]; // saved object client does not support sorting by title because title is only mapped as analyzed // the legacy implementation got around this by pulling `listingLimit` items and doing client side sorting @@ -52,6 +53,12 @@ class TableListViewUi extends React.Component { constructor(props) { super(props); + const initialPageSize = npStart.core.uiSettings.get('savedObjects:perPage'); + this.pagination = { + initialPageIndex: 0, + initialPageSize, + pageSizeOptions: _.uniq([10, 20, 50, initialPageSize]).sort(), + }; this.state = { items: [], totalItems: 0, @@ -62,8 +69,6 @@ class TableListViewUi extends React.Component { showLimitError: false, filter: this.props.initialFilter, selectedIds: [], - page: 0, - perPage: 20, }; } @@ -116,7 +121,8 @@ class TableListViewUi extends React.Component { isDeletingItems: true }); try { - await this.props.deleteItems(this.state.selectedIds); + const itemsById = _.indexBy(this.state.items, 'id'); + await this.props.deleteItems(this.state.selectedIds.map(id => itemsById[id])); } catch (error) { toastNotifications.addDanger({ title: ( @@ -308,13 +314,6 @@ class TableListViewUi extends React.Component { } renderTable() { - const pagination = { - pageIndex: this.state.page, - pageSize: this.state.perPage, - totalItemCount: this.state.items.length, - pageSizeOptions: PAGE_SIZE_OPTIONS, - }; - const selection = this.props.deleteItems ? { onSelectionChange: (selection) => { this.setState({ @@ -367,7 +366,7 @@ class TableListViewUi extends React.Component { itemId="id" items={this.state.items} columns={columns} - pagination={pagination} + pagination={this.pagination} loading={this.state.isFetchingItems} message={noItemsMessage} selection={selection} @@ -482,4 +481,3 @@ TableListViewUi.defaultProps = { }; export const TableListView = injectI18n(TableListViewUi); - diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html index 101a458198290..8513deee800e3 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.html @@ -23,25 +23,26 @@
    - - - - + - - +
    diff --git a/src/legacy/core_plugins/timelion/server/index.ts b/src/legacy/core_plugins/timelion/server/index.ts new file mode 100644 index 0000000000000..36af9ce7b85df --- /dev/null +++ b/src/legacy/core_plugins/timelion/server/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. + */ + +import { PluginInitializerContext } from 'kibana/server'; +import { TimelionServerPlugin as Plugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new Plugin(initializerContext); +} diff --git a/src/legacy/core_plugins/timelion/server/lib/classes/timelion_function.d.ts b/src/legacy/core_plugins/timelion/server/lib/classes/timelion_function.d.ts new file mode 100644 index 0000000000000..6e32a4454e707 --- /dev/null +++ b/src/legacy/core_plugins/timelion/server/lib/classes/timelion_function.d.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. + */ + +export interface TimelionFunctionInterface extends TimelionFunctionConfig { + chainable: boolean; + originalFn: Function; + argsByName: TimelionFunctionArgs[]; +} + +export interface TimelionFunctionConfig { + name: string; + help: string; + extended: boolean; + aliases: string[]; + fn: Function; + args: TimelionFunctionArgs[]; +} + +export interface TimelionFunctionArgs { + name: string; + help?: string; + multi?: boolean; + types: TimelionFunctionArgsTypes[]; + suggestions?: TimelionFunctionArgsSuggestion[]; +} + +export type TimelionFunctionArgsTypes = 'seriesList' | 'number' | 'string' | 'boolean' | 'null'; + +export interface TimelionFunctionArgsSuggestion { + name: string; + help: string; +} + +// eslint-disable-next-line import/no-default-export +export default class TimelionFunction { + constructor(name: string, config: TimelionFunctionConfig); +} diff --git a/src/legacy/core_plugins/timelion/server/lib/load_functions.d.ts b/src/legacy/core_plugins/timelion/server/lib/load_functions.d.ts new file mode 100644 index 0000000000000..f6d04ee875831 --- /dev/null +++ b/src/legacy/core_plugins/timelion/server/lib/load_functions.d.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 { TimelionFunctionInterface } from '../types'; + +declare function loadFunctions(directory: string): LoadFunctions; + +export interface LoadFunctions { + [key: string]: TimelionFunctionInterface; +} + +// eslint-disable-next-line import/no-default-export +export default loadFunctions; diff --git a/src/legacy/core_plugins/timelion/server/plugin.ts b/src/legacy/core_plugins/timelion/server/plugin.ts new file mode 100644 index 0000000000000..c94277ebc7adc --- /dev/null +++ b/src/legacy/core_plugins/timelion/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 { Legacy } from 'kibana'; +import { i18n } from '@kbn/i18n'; +import { PluginInitializerContext, CoreSetup } from 'kibana/server'; + +import loadFunctions, { LoadFunctions } from './lib/load_functions'; +import { initRoutes } from './routes'; + +function getFunction(functions: LoadFunctions, name: string) { + if (functions[name]) { + return functions[name]; + } + + throw new Error( + i18n.translate('timelion.noFunctionErrorMessage', { + defaultMessage: 'No such function: {name}', + values: { name }, + }) + ); +} + +// TODO: Remove as CoreSetup is completed. +export interface CustomCoreSetup { + http: { + server: Legacy.Server; + }; +} + +export class TimelionServerPlugin { + public initializerContext: PluginInitializerContext; + + constructor(initializerContext: PluginInitializerContext) { + this.initializerContext = initializerContext; + } + + public setup(core: CoreSetup & CustomCoreSetup) { + const { server } = core.http; + const functions = loadFunctions('series_functions'); + + server.expose('functions', functions); + server.expose('getFunction', (name: string) => getFunction(functions, name)); + + initRoutes(server); + } +} diff --git a/src/legacy/core_plugins/timelion/server/routes/functions.js b/src/legacy/core_plugins/timelion/server/routes/functions.js index 2fd97e38a0057..ff8b750cf1ec2 100644 --- a/src/legacy/core_plugins/timelion/server/routes/functions.js +++ b/src/legacy/core_plugins/timelion/server/routes/functions.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -export default function (server) { +export function functionsRoute(server) { server.route({ method: 'GET', path: '/api/timelion/functions', diff --git a/src/legacy/core_plugins/timelion/server/routes/index.ts b/src/legacy/core_plugins/timelion/server/routes/index.ts new file mode 100644 index 0000000000000..b6438c81ef002 --- /dev/null +++ b/src/legacy/core_plugins/timelion/server/routes/index.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 { Legacy } from 'kibana'; + +// @ts-ignore +import { runRoute } from './run'; +// @ts-ignore +import { functionsRoute } from './functions'; +// @ts-ignore +import { validateEsRoute } from './validate_es'; + +export function initRoutes(server: Legacy.Server) { + runRoute(server); + functionsRoute(server); + validateEsRoute(server); +} diff --git a/src/legacy/core_plugins/timelion/server/routes/run.js b/src/legacy/core_plugins/timelion/server/routes/run.js index e4c3b447b3970..a2d5bd23fe9a9 100644 --- a/src/legacy/core_plugins/timelion/server/routes/run.js +++ b/src/legacy/core_plugins/timelion/server/routes/run.js @@ -29,8 +29,7 @@ function formatErrorResponse(e, h) { }).code(500); } - -export default function (server) { +export function runRoute(server) { server.route({ method: ['POST', 'GET'], path: '/api/timelion/run', @@ -71,5 +70,4 @@ export default function (server) { } } }); - } diff --git a/src/legacy/core_plugins/timelion/server/routes/validate_es.js b/src/legacy/core_plugins/timelion/server/routes/validate_es.js index d2b4e366c0ba4..350f6fd656010 100644 --- a/src/legacy/core_plugins/timelion/server/routes/validate_es.js +++ b/src/legacy/core_plugins/timelion/server/routes/validate_es.js @@ -19,7 +19,7 @@ import _ from 'lodash'; -export default function (server) { +export function validateEsRoute(server) { server.route({ method: 'GET', path: '/api/timelion/validate/es', diff --git a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/color.js b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/color.js index 57c570f004716..dfe9bfc3988e7 100644 --- a/src/legacy/core_plugins/timelion/server/series_functions/__tests__/color.js +++ b/src/legacy/core_plugins/timelion/server/series_functions/__tests__/color.js @@ -59,6 +59,18 @@ describe('color.js', () => { expect(seriesColors).to.eql(['#000000', '#111111', '#222222', '#333333', '#444444']); }); + it('should work with series.length=1 and more colors', async () => { + const oneLongList = { + type: 'seriesList', + list: seriesList.list.slice(0, 1) + }; + const colorsArg = '#000:#111'; + + const r = await invoke(fn, [oneLongList, colorsArg]); + const seriesColors = _.map(r.output.list, 'color'); + expect(seriesColors).to.eql(['#000']); + }); + it('throws if you do not pass a color', () => { invoke(fn, [seriesList, '']).catch((e) => { expect(e).to.be.an(Error); diff --git a/src/legacy/core_plugins/timelion/server/series_functions/color.js b/src/legacy/core_plugins/timelion/server/series_functions/color.js index 57fed6ebe8cca..fa13a4463db36 100644 --- a/src/legacy/core_plugins/timelion/server/series_functions/color.js +++ b/src/legacy/core_plugins/timelion/server/series_functions/color.js @@ -58,7 +58,7 @@ colors, and have multiple series, you will get a gradient, e.g., "#00B1CC:#00FF9 return alter(args, function (eachSeries) { if (gradient) { eachSeries.color = gradient[i++].toHexString(); - } else if (colors.length === 1) { + } else if (colors.length === 1 || gradientStops === 1) { eachSeries.color = colors[0]; } else { throw new Error( diff --git a/src/legacy/core_plugins/timelion/server/types.ts b/src/legacy/core_plugins/timelion/server/types.ts new file mode 100644 index 0000000000000..4971fa34863d3 --- /dev/null +++ b/src/legacy/core_plugins/timelion/server/types.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + TimelionFunctionInterface, + TimelionFunctionConfig, + TimelionFunctionArgs, + TimelionFunctionArgsSuggestion, + TimelionFunctionArgsTypes, +} from './lib/classes/timelion_function'; diff --git a/src/legacy/core_plugins/vis_type_markdown/index.ts b/src/legacy/core_plugins/vis_type_markdown/index.ts index 5bfea17be5824..8106e5d30ddd0 100644 --- a/src/legacy/core_plugins/vis_type_markdown/index.ts +++ b/src/legacy/core_plugins/vis_type_markdown/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const markdownPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'markdown_vis', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'data'], + require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_markdown/public/_markdown_vis.scss b/src/legacy/core_plugins/vis_type_markdown/public/_markdown_vis.scss index 8c66e7859752a..da38d6d2ed211 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/_markdown_vis.scss +++ b/src/legacy/core_plugins/vis_type_markdown/public/_markdown_vis.scss @@ -1,9 +1,20 @@ .mkdVis { padding: $euiSizeS; width: 100%; - } -#markdownVisInput { - resize: none; +.visEditor--markdown { + vis-editor-vis-options, vis-options-react-wrapper { + flex-grow: 1; + display: flex; + flex-direction: column; + } + + .visEditor--markdown__textarea { + flex-grow: 1; + } + + .mkdEditor { + height: 100%; + } } diff --git a/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts b/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts index 769fc72b4c661..6074137532ae9 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts @@ -20,13 +20,13 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { visualizations } from '../../visualizations/public'; +import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; import { MarkdownPluginSetupDependencies } from './plugin'; import { plugin } from '.'; const plugins: Readonly = { - visualizations, - data: npSetup.plugins.data, + expressions: npSetup.plugins.expressions, + visualizations: visualizationsSetup, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.ts b/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.ts index bfd83c1f07b6a..8107a29ad2056 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/markdown_fn.ts @@ -19,24 +19,12 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunction, Render } from '../../interpreter/types'; -import { Style } from '../../interpreter/public/types'; +import { Arguments, MarkdownVisParams } from './types'; const name = 'markdownVis'; type Context = undefined; -interface Arguments { - markdown: string; - font: Style; - openLinksInNewTab: boolean; -} - -export interface MarkdownVisParams { - markdown: Arguments['markdown']; - openLinksInNewTab: Arguments['openLinksInNewTab']; - fontSize: number; -} - interface RenderValue { visType: 'markdown'; visConfig: MarkdownVisParams; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_options.tsx b/src/legacy/core_plugins/vis_type_markdown/public/markdown_options.tsx new file mode 100644 index 0000000000000..79628afe48531 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_markdown/public/markdown_options.tsx @@ -0,0 +1,86 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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, { useCallback } from 'react'; +import { + EuiPanel, + EuiTitle, + EuiLink, + EuiIcon, + EuiTextArea, + EuiFlexGroup, + EuiFlexItem, + EuiText, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { VisOptionsProps } from 'ui/vis/editors/default'; +import { MarkdownVisParams } from './types'; + +function MarkdownOptions({ stateParams, setValue }: VisOptionsProps) { + const onMarkdownUpdate = useCallback( + (value: MarkdownVisParams['markdown']) => setValue('markdown', value), + [] + ); + + return ( + + + + + + +

    Markdown

    +
    +
    + + + + + {' '} + + + + +
    +
    + + + onMarkdownUpdate(value)} + fullWidth={true} + data-test-subj="markdownTextarea" + resize="none" + /> + +
    +
    + ); +} + +export { MarkdownOptions }; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis.ts b/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis.ts index 1e8bacd2a3f9e..7b2f8f6c236b2 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis.ts @@ -22,7 +22,8 @@ import { i18n } from '@kbn/i18n'; import { visFactory, DefaultEditorSize } from '../../visualizations/public'; import { MarkdownVisWrapper } from './markdown_vis_controller'; -import markdownVisParamsTemplate from './markdown_vis_params.html'; +import { MarkdownOptions } from './markdown_options'; +import { SettingsOptions } from './settings_options'; export const markdownVis = visFactory.createReactVisualization({ name: 'markdown', @@ -41,7 +42,22 @@ export const markdownVis = visFactory.createReactVisualization({ }, }, editorConfig: { - optionsTemplate: markdownVisParamsTemplate, + optionTabs: [ + { + name: 'advanced', + title: i18n.translate('visTypeMarkdown.tabs.dataText', { + defaultMessage: 'Data', + }), + editor: MarkdownOptions, + }, + { + name: 'options', + title: i18n.translate('visTypeMarkdown.tabs.optionsText', { + defaultMessage: 'Options', + }), + editor: SettingsOptions, + }, + ], enableAutoApply: true, defaultSize: DefaultEditorSize.LARGE, }, diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx b/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx index 103879cb6e6df..9d2f68ddb7446 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx +++ b/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx @@ -21,6 +21,11 @@ import React from 'react'; import { render, mount } from 'enzyme'; import { MarkdownVisWrapper } from './markdown_vis_controller'; +// We need Markdown to do these tests, so mock data plugin +jest.mock('../../data/public', () => { + return {}; +}); + describe('markdown vis controller', () => { it('should set html from markdown params', () => { const vis = { diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.tsx b/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.tsx index f07e126b268d1..4e77bb196b713 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.tsx +++ b/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_controller.tsx @@ -18,8 +18,8 @@ */ import React from 'react'; -import { Markdown } from 'ui/markdown/markdown'; -import { MarkdownVisParams } from './markdown_fn'; +import { Markdown } from '../../kibana_react/public'; +import { MarkdownVisParams } from './types'; interface MarkdownVisComponentProps extends MarkdownVisParams { renderComplete: () => {}; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_params.html b/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_params.html deleted file mode 100644 index 2750e5c1b3b39..0000000000000 --- a/src/legacy/core_plugins/vis_type_markdown/public/markdown_vis_params.html +++ /dev/null @@ -1,54 +0,0 @@ -
    -
    - -
    - -
    - -
    -
    -
    - -
    - -
    -
    - -
    -
    diff --git a/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts b/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts index 286b233280382..85d8c27ed970d 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts @@ -18,7 +18,7 @@ */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; -import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public'; +import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; import { markdownVis } from './markdown_vis'; @@ -26,7 +26,7 @@ import { createMarkdownVisFn } from './markdown_fn'; /** @internal */ export interface MarkdownPluginSetupDependencies { - data: ReturnType; + expressions: ReturnType; visualizations: VisualizationsSetup; } @@ -38,9 +38,9 @@ export class MarkdownPlugin implements Plugin { this.initializerContext = initializerContext; } - public setup(core: CoreSetup, { data, visualizations }: MarkdownPluginSetupDependencies) { - visualizations.types.VisTypesRegistryProvider.register(() => markdownVis); - data.expressions.registerFunction(createMarkdownVisFn); + public setup(core: CoreSetup, { expressions, visualizations }: MarkdownPluginSetupDependencies) { + visualizations.types.registerVisualization(() => markdownVis); + expressions.registerFunction(createMarkdownVisFn); } public start(core: CoreStart) { diff --git a/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx new file mode 100644 index 0000000000000..91bdbf118d16f --- /dev/null +++ b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.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 { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { VisOptionsProps } from 'ui/vis/editors/default'; +import { RangeOption, SwitchOption } from '../../kbn_vislib_vis_types/public/components'; +import { MarkdownVisParams } from './types'; + +function SettingsOptions({ stateParams, setValue }: VisOptionsProps) { + return ( + + +

    + +

    +
    + + + + + +
    + ); +} + +export { SettingsOptions }; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/types.ts b/src/legacy/core_plugins/vis_type_markdown/public/types.ts new file mode 100644 index 0000000000000..28156e6bb5c49 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_markdown/public/types.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 { Style } from '../../interpreter/public/types'; + +export interface Arguments { + markdown: string; + font: Style; + openLinksInNewTab: boolean; +} + +export interface MarkdownVisParams { + markdown: Arguments['markdown']; + openLinksInNewTab: Arguments['openLinksInNewTab']; + fontSize: number; +} diff --git a/src/legacy/core_plugins/vis_type_metric/index.ts b/src/legacy/core_plugins/vis_type_metric/index.ts index f77234a26ce48..f71fc4a75461e 100644 --- a/src/legacy/core_plugins/vis_type_metric/index.ts +++ b/src/legacy/core_plugins/vis_type_metric/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const metricPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'metric_vis', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'data'], + require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis.js b/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis.js index 7adf7007e8603..f5fb6312d2b0a 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis.js +++ b/src/legacy/core_plugins/vis_type_metric/public/__tests__/metric_vis.js @@ -24,7 +24,7 @@ import expect from '@kbn/expect'; import { VisProvider } from 'ui/vis'; import LogstashIndexPatternStubProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { visualizations } from '../../../visualizations/public'; +import { setup as visualizationsSetup } from '../../../visualizations/public/legacy'; import { createMetricVisTypeDefinition } from '../metric_vis_type'; describe('metric_vis - createMetricVisTypeDefinition', () => { @@ -32,48 +32,52 @@ describe('metric_vis - createMetricVisTypeDefinition', () => { let vis; beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject((Private) => { - setup = () => { - const Vis = Private(VisProvider); - const metricVisType = createMetricVisTypeDefinition(); - - visualizations.types.VisTypesRegistryProvider.register(() => - metricVisType - ); - - const indexPattern = Private(LogstashIndexPatternStubProvider); - - indexPattern.stubSetFieldFormat('ip', 'url', { - urlTemplate: 'http://ip.info?address={{value}}', - labelTemplate: 'ip[{{value}}]' - }); - - vis = new Vis(indexPattern, { - type: 'metric', - aggs: [{ id: '1', type: 'top_hits', schema: 'metric', params: { field: 'ip' } }], - }); - - vis.params.dimensions = { - metrics: [{ - accessor: 0, format: { - id: 'url', params: { - urlTemplate: 'http://ip.info?address={{value}}', - labelTemplate: 'ip[{{value}}]' - } - } - }] - }; - - const el = document.createElement('div'); - const Controller = metricVisType.visualization; - const controller = new Controller(el, vis); - const render = (esResponse) => { - controller.render(esResponse, vis.params); + beforeEach( + ngMock.inject(Private => { + setup = () => { + const Vis = Private(VisProvider); + const metricVisType = createMetricVisTypeDefinition(); + + visualizationsSetup.types.registerVisualization(() => metricVisType); + + const indexPattern = Private(LogstashIndexPatternStubProvider); + + indexPattern.stubSetFieldFormat('ip', 'url', { + urlTemplate: 'http://ip.info?address={{value}}', + labelTemplate: 'ip[{{value}}]', + }); + + vis = new Vis(indexPattern, { + type: 'metric', + aggs: [{ id: '1', type: 'top_hits', schema: 'metric', params: { field: 'ip' } }], + }); + + vis.params.dimensions = { + metrics: [ + { + accessor: 0, + format: { + id: 'url', + params: { + urlTemplate: 'http://ip.info?address={{value}}', + labelTemplate: 'ip[{{value}}]', + }, + }, + }, + ], + }; + + const el = document.createElement('div'); + const Controller = metricVisType.visualization; + const controller = new Controller(el, vis); + const render = esResponse => { + controller.render(esResponse, vis.params); + }; + + return { el, render }; }; - - return { el, render }; - }; - })); + }) + ); it('renders html value from field formatter', () => { const { el, render } = setup(); @@ -81,12 +85,14 @@ describe('metric_vis - createMetricVisTypeDefinition', () => { const ip = '235.195.237.208'; render({ columns: [{ id: 'col-0', name: 'ip' }], - rows: [{ 'col-0': ip }] + rows: [{ 'col-0': ip }], }); const $link = $(el) .find('a[href]') - .filter(function () { return this.href.includes('ip.info'); }); + .filter(function () { + return this.href.includes('ip.info'); + }); expect($link).to.have.length(1); expect($link.text()).to.be(`ip[${ip}]`); diff --git a/src/legacy/core_plugins/vis_type_metric/public/legacy.ts b/src/legacy/core_plugins/vis_type_metric/public/legacy.ts index 4ab399977d7b1..c5fc86c7e35f5 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/legacy.ts @@ -20,14 +20,14 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { visualizations } from '../../visualizations/public'; +import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; import { MetricVisPluginSetupDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; const plugins: Readonly = { - visualizations, - data: npSetup.plugins.data, + expressions: npSetup.plugins.expressions, + visualizations: visualizationsSetup, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/vis_type_metric/public/plugin.ts b/src/legacy/core_plugins/vis_type_metric/public/plugin.ts index d99df03fcc560..1c5dbbd03a18d 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/plugin.ts @@ -19,7 +19,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; import { LegacyDependenciesPlugin } from './shim'; -import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public'; +import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; import { createMetricVisFn } from './metric_vis_fn'; @@ -28,7 +28,7 @@ import { createMetricVisTypeDefinition } from './metric_vis_type'; /** @internal */ export interface MetricVisPluginSetupDependencies { - data: ReturnType; + expressions: ReturnType; visualizations: VisualizationsSetup; __LEGACY: LegacyDependenciesPlugin; } @@ -43,12 +43,12 @@ export class MetricVisPlugin implements Plugin { public setup( core: CoreSetup, - { data, visualizations, __LEGACY }: MetricVisPluginSetupDependencies + { expressions, visualizations, __LEGACY }: MetricVisPluginSetupDependencies ) { __LEGACY.setup(); - data.expressions.registerFunction(createMetricVisFn); - visualizations.types.VisTypesRegistryProvider.register(createMetricVisTypeDefinition); + expressions.registerFunction(createMetricVisFn); + visualizations.types.registerVisualization(createMetricVisTypeDefinition); } public start(core: CoreStart) { diff --git a/src/legacy/core_plugins/vis_type_table/index.ts b/src/legacy/core_plugins/vis_type_table/index.ts index 2580932f03132..3847dd6b58268 100644 --- a/src/legacy/core_plugins/vis_type_table/index.ts +++ b/src/legacy/core_plugins/vis_type_table/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const tableVisPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'table_vis', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'data'], + require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js index c8f8194f7f98a..f04c953f070ae 100644 --- a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js +++ b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js @@ -28,7 +28,7 @@ import { AppStateProvider } from 'ui/state_management/app_state'; import { tabifyAggResponse } from 'ui/agg_response/tabify'; import { createTableVisTypeDefinition } from '../table_vis_type'; -import { visualizations } from '../../../visualizations/public'; +import { setup as visualizationsSetup } from '../../../visualizations/public/legacy'; describe('Table Vis - Controller', async function () { let $rootScope; @@ -44,68 +44,73 @@ describe('Table Vis - Controller', async function () { let legacyDependencies; beforeEach(ngMock.module('kibana', 'kibana/table_vis')); - beforeEach(ngMock.inject(function ($injector) { - Private = $injector.get('Private'); - legacyDependencies = { - // eslint-disable-next-line new-cap - createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization - }; - - visualizations.types.VisTypesRegistryProvider.register(() => - createTableVisTypeDefinition(legacyDependencies) - ); - - $rootScope = $injector.get('$rootScope'); - $compile = $injector.get('$compile'); - fixtures = require('fixtures/fake_hierarchical_data'); - AppState = Private(AppStateProvider); - Vis = Private(VisProvider); - tableAggResponse = legacyResponseHandlerProvider().handler; - })); + beforeEach( + ngMock.inject(function ($injector) { + Private = $injector.get('Private'); + legacyDependencies = { + // eslint-disable-next-line new-cap + createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization, + }; + + visualizationsSetup.types.registerVisualization(() => + createTableVisTypeDefinition(legacyDependencies) + ); + + $rootScope = $injector.get('$rootScope'); + $compile = $injector.get('$compile'); + fixtures = require('fixtures/fake_hierarchical_data'); + AppState = Private(AppStateProvider); + Vis = Private(VisProvider); + tableAggResponse = legacyResponseHandlerProvider().handler; + }) + ); function OneRangeVis(params) { - return new Vis( - Private(FixturesStubbedLogstashIndexPatternProvider), - { - type: 'table', - params: params || {}, - aggs: [ - { type: 'count', schema: 'metric' }, - { - type: 'range', - schema: 'bucket', - params: { - field: 'bytes', - ranges: [ - { from: 0, to: 1000 }, - { from: 1000, to: 2000 } - ] - } - } - ] - } - ); + return new Vis(Private(FixturesStubbedLogstashIndexPatternProvider), { + type: 'table', + params: params || {}, + aggs: [ + { type: 'count', schema: 'metric' }, + { + type: 'range', + schema: 'bucket', + params: { + field: 'bytes', + ranges: [{ from: 0, to: 1000 }, { from: 1000, to: 2000 }], + }, + }, + ], + }); } const dimensions = { - buckets: [{ - accessor: 0, - }], metrics: [{ - accessor: 1, - format: { id: 'range' }, - }] + buckets: [ + { + accessor: 0, + }, + ], + metrics: [ + { + accessor: 1, + format: { id: 'range' }, + }, + ], }; // basically a parameterized beforeEach function initController(vis) { - vis.aggs.forEach(function (agg, i) { agg.id = 'agg_' + (i + 1); }); + vis.aggs.aggs.forEach(function (agg, i) { + agg.id = 'agg_' + (i + 1); + }); tabifiedResponse = tabifyAggResponse(vis.aggs, fixtures.oneRangeBucket); $rootScope.vis = vis; $rootScope.visParams = vis.params; $rootScope.uiState = new AppState({ uiState: {} }).makeStateful('uiState'); $rootScope.renderComplete = () => {}; - $rootScope.newScope = function (scope) { $scope = scope; }; + $rootScope.newScope = function (scope) { + $scope = scope; + }; $el = $('
    ') .attr('ng-controller', 'KbnTableVisController') @@ -157,7 +162,7 @@ describe('Table Vis - Controller', async function () { it('sets the sort on the scope when it is passed as a vis param', async function () { const sortObj = { columnIndex: 1, - direction: 'asc' + direction: 'asc', }; const vis = new OneRangeVis({ sort: sortObj }); initController(vis); @@ -181,7 +186,6 @@ describe('Table Vis - Controller', async function () { }); it('passes partialRows:true to tabify based on the vis params', function () { - const vis = new OneRangeVis({ showPartialRows: true }); initController(vis); @@ -189,7 +193,6 @@ describe('Table Vis - Controller', async function () { }); it('passes partialRows:false to tabify based on the vis params', function () { - const vis = new OneRangeVis({ showPartialRows: false }); initController(vis); diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js index 5c2940ff40efe..323201ded73a3 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js @@ -31,10 +31,9 @@ import { round } from 'lodash'; import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { createTableVisTypeDefinition } from '../../table_vis_type'; -import { visualizations } from '../../../../visualizations/public'; +import { setup as visualizationsSetup } from '../../../../visualizations/public/legacy'; describe('Table Vis - AggTable Directive', function () { - let $rootScope; let $compile; let Vis; @@ -51,19 +50,21 @@ describe('Table Vis - AggTable Directive', function () { const vis2 = new Vis(indexPattern, { type: 'table', params: { - showMetricsAtAllLevels: true + showMetricsAtAllLevels: true, }, aggs: [ { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, { type: 'terms', schema: 'bucket', params: { field: 'extension' } }, { type: 'terms', schema: 'bucket', params: { field: 'geo.src' } }, - { type: 'terms', schema: 'bucket', params: { field: 'machine.os' } } - ] + { type: 'terms', schema: 'bucket', params: { field: 'machine.os' } }, + ], }); - vis2.aggs.forEach(function (agg, i) { + vis2.aggs.aggs.forEach(function (agg, i) { agg.id = 'agg_' + (i + 1); }); - tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, fixtures.threeTermBuckets, { metricsAtAllLevels: true }); + tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, fixtures.threeTermBuckets, { + metricsAtAllLevels: true, + }); const vis3 = new Vis(indexPattern, { type: 'table', @@ -71,41 +72,54 @@ describe('Table Vis - AggTable Directive', function () { { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, { type: 'min', schema: 'metric', params: { field: '@timestamp' } }, { type: 'terms', schema: 'bucket', params: { field: 'extension' } }, - { type: 'date_histogram', schema: 'bucket', params: { field: '@timestamp', interval: 'd' } }, - { type: 'derivative', schema: 'metric', - params: { metricAgg: 'custom', customMetric: { id: '5-orderAgg', type: 'count' } } }, - { type: 'top_hits', schema: 'metric', params: { field: 'bytes', aggregate: { val: 'min' }, size: 1 } } - ] + { + type: 'date_histogram', + schema: 'bucket', + params: { field: '@timestamp', interval: 'd' }, + }, + { + type: 'derivative', + schema: 'metric', + params: { metricAgg: 'custom', customMetric: { id: '5-orderAgg', type: 'count' } }, + }, + { + type: 'top_hits', + schema: 'metric', + params: { field: 'bytes', aggregate: { val: 'min' }, size: 1 }, + }, + ], }); - vis3.aggs.forEach(function (agg, i) { + vis3.aggs.aggs.forEach(function (agg, i) { agg.id = 'agg_' + (i + 1); }); - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = - tabifyAggResponse(vis3.aggs, fixtures.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative); + tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = tabifyAggResponse( + vis3.aggs, + fixtures.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative + ); }; beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function ($injector, Private, config) { - legacyDependencies = { - // eslint-disable-next-line new-cap - createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization - }; + beforeEach( + ngMock.inject(function ($injector, Private, config) { + legacyDependencies = { + // eslint-disable-next-line new-cap + createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization, + }; - visualizations.types.VisTypesRegistryProvider.register(() => - createTableVisTypeDefinition(legacyDependencies) - ); + visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies)); - tableAggResponse = legacyResponseHandlerProvider().handler; - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - Vis = Private(VisProvider); - settings = config; + tableAggResponse = legacyResponseHandlerProvider().handler; + indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + Vis = Private(VisProvider); + settings = config; - $rootScope = $injector.get('$rootScope'); - $compile = $injector.get('$compile'); + $rootScope = $injector.get('$rootScope'); + $compile = $injector.get('$compile'); - init(); - })); + init(); + }) + ); let $scope; beforeEach(function () { @@ -115,12 +129,16 @@ describe('Table Vis - AggTable Directive', function () { $scope.$destroy(); }); - it('renders a simple response properly', async function () { - $scope.dimensions = { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [] }; + $scope.dimensions = { + metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], + buckets: [], + }; $scope.table = (await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions)).tables[0]; - const $el = $compile('')($scope); + const $el = $compile('')( + $scope + ); $scope.$digest(); expect($el.find('tbody').length).to.be(1); @@ -131,7 +149,9 @@ describe('Table Vis - AggTable Directive', function () { it('renders nothing if the table is empty', function () { $scope.dimensions = {}; $scope.table = null; - const $el = $compile('')($scope); + const $el = $compile('')( + $scope + ); $scope.$digest(); expect($el.find('tbody').length).to.be(0); @@ -139,10 +159,21 @@ describe('Table Vis - AggTable Directive', function () { it('renders a complex response properly', async function () { $scope.dimensions = { - buckets: [{ accessor: 0, params: {} }, { accessor: 2, params: {} }, { accessor: 4, params: {} }], - metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }] + buckets: [ + { accessor: 0, params: {} }, + { accessor: 2, params: {} }, + { accessor: 4, params: {} }, + ], + metrics: [ + { accessor: 1, params: {} }, + { accessor: 3, params: {} }, + { accessor: 5, params: {} }, + ], }; - $scope.table = (await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)).tables[0]; + $scope.table = (await tableAggResponse( + tabifiedData.threeTermBuckets, + $scope.dimensions + )).tables[0]; const $el = $(''); $compile($el)($scope); $scope.$digest(); @@ -165,7 +196,9 @@ describe('Table Vis - AggTable Directive', function () { expect($cells.length).to.be(6); const txts = $cells.map(function () { - return $(this).text().trim(); + return $(this) + .text() + .trim(); }); // two character country code @@ -184,7 +217,6 @@ describe('Table Vis - AggTable Directive', function () { describe('renders totals row', function () { async function totalsRowTest(totalFunc, expected) { - function setDefaultTimezone() { moment.tz.setDefault(settings.get('dateFormat:tz')); } @@ -197,15 +229,18 @@ describe('Table Vis - AggTable Directive', function () { buckets: [ { accessor: 0, params: {} }, { accessor: 1, format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } } }, - ], metrics: [ + ], + metrics: [ { accessor: 2, format: { id: 'number' } }, { accessor: 3, format: { id: 'date' } }, { accessor: 4, format: { id: 'number' } }, { accessor: 5, format: { id: 'number' } }, - ] + ], }; const response = await tableAggResponse( - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, $scope.dimensions); + tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, + $scope.dimensions + ); $scope.table = response.tables[0]; $scope.showTotal = true; $scope.totalFunc = totalFunc; @@ -226,7 +261,11 @@ describe('Table Vis - AggTable Directive', function () { expect($cells.length).to.be(6); for (let i = 0; i < 6; i++) { - expect($($cells[i]).text().trim()).to.be(expected[i]); + expect( + $($cells[i]) + .text() + .trim() + ).to.be(expected[i]); } settings.set('dateFormat:tz', oldTimezoneSetting); off(); @@ -241,7 +280,7 @@ describe('Table Vis - AggTable Directive', function () { '9,283', 'Sep 28, 2014 @ 00:00:00.000', '1', - '11' + '11', ]); }); it('as max', async function () { @@ -251,34 +290,22 @@ describe('Table Vis - AggTable Directive', function () { '220,943', 'Oct 3, 2014 @ 00:00:00.000', '239', - '837' + '837', ]); }); it('as avg', async function () { - await totalsRowTest('avg', [ - '', - '', - '87,221.5', - '', - '64.667', - '206.833' - ]); + await totalsRowTest('avg', ['', '', '87,221.5', '', '64.667', '206.833']); }); it('as sum', async function () { - await totalsRowTest('sum', [ - '', - '', - '1,569,987', - '', - '1,164', - '3,723' - ]); + await totalsRowTest('sum', ['', '', '1,569,987', '', '1,164', '3,723']); }); }); describe('aggTable.toCsv()', function () { it('escapes rows and columns properly', function () { - const $el = $compile('')($scope); + const $el = $compile('')( + $scope + ); $scope.$digest(); const $tableScope = $el.isolateScope(); @@ -289,25 +316,35 @@ describe('Table Vis - AggTable Directive', function () { { id: 'b', name: 'two' }, { id: 'c', name: 'with double-quotes(")' }, ], - rows: [ - { a: 1, b: 2, c: '"foobar"' }, - ], + rows: [{ a: 1, b: 2, c: '"foobar"' }], }; expect(aggTable.toCsv()).to.be( - 'one,two,"with double-quotes("")"' + '\r\n' + - '1,2,"""foobar"""' + '\r\n' + 'one,two,"with double-quotes("")"' + '\r\n' + '1,2,"""foobar"""' + '\r\n' ); }); it('exports rows and columns properly', async function () { $scope.dimensions = { - buckets: [{ accessor: 0, params: {} }, { accessor: 2, params: {} }, { accessor: 4, params: {} }], - metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }] + buckets: [ + { accessor: 0, params: {} }, + { accessor: 2, params: {} }, + { accessor: 4, params: {} }, + ], + metrics: [ + { accessor: 1, params: {} }, + { accessor: 3, params: {} }, + { accessor: 5, params: {} }, + ], }; - $scope.table = (await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)).tables[0]; + $scope.table = (await tableAggResponse( + tabifiedData.threeTermBuckets, + $scope.dimensions + )).tables[0]; - const $el = $compile('')($scope); + const $el = $compile('')( + $scope + ); $scope.$digest(); const $tableScope = $el.isolateScope(); @@ -316,30 +353,56 @@ describe('Table Vis - AggTable Directive', function () { const raw = aggTable.toCsv(false); expect(raw).to.be( - '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + '\r\n' + - 'png,IT,win,412032,9299,0' + '\r\n' + - 'png,IT,mac,412032,9299,9299' + '\r\n' + - 'png,US,linux,412032,8293,3992' + '\r\n' + - 'png,US,mac,412032,8293,3029' + '\r\n' + - 'css,MX,win,412032,9299,4992' + '\r\n' + - 'css,MX,mac,412032,9299,5892' + '\r\n' + - 'css,US,linux,412032,8293,3992' + '\r\n' + - 'css,US,mac,412032,8293,3029' + '\r\n' + - 'html,CN,win,412032,9299,4992' + '\r\n' + - 'html,CN,mac,412032,9299,5892' + '\r\n' + - 'html,FR,win,412032,8293,3992' + '\r\n' + - 'html,FR,mac,412032,8293,3029' + '\r\n' + '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + + '\r\n' + + 'png,IT,win,412032,9299,0' + + '\r\n' + + 'png,IT,mac,412032,9299,9299' + + '\r\n' + + 'png,US,linux,412032,8293,3992' + + '\r\n' + + 'png,US,mac,412032,8293,3029' + + '\r\n' + + 'css,MX,win,412032,9299,4992' + + '\r\n' + + 'css,MX,mac,412032,9299,5892' + + '\r\n' + + 'css,US,linux,412032,8293,3992' + + '\r\n' + + 'css,US,mac,412032,8293,3029' + + '\r\n' + + 'html,CN,win,412032,9299,4992' + + '\r\n' + + 'html,CN,mac,412032,9299,5892' + + '\r\n' + + 'html,FR,win,412032,8293,3992' + + '\r\n' + + 'html,FR,mac,412032,8293,3029' + + '\r\n' ); }); it('exports formatted rows and columns properly', async function () { $scope.dimensions = { - buckets: [{ accessor: 0, params: {} }, { accessor: 2, params: {} }, { accessor: 4, params: {} }], - metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }] + buckets: [ + { accessor: 0, params: {} }, + { accessor: 2, params: {} }, + { accessor: 4, params: {} }, + ], + metrics: [ + { accessor: 1, params: {} }, + { accessor: 3, params: {} }, + { accessor: 5, params: {} }, + ], }; - $scope.table = (await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)).tables[0]; + $scope.table = (await tableAggResponse( + tabifiedData.threeTermBuckets, + $scope.dimensions + )).tables[0]; - const $el = $compile('')($scope); + const $el = $compile('')( + $scope + ); $scope.$digest(); const $tableScope = $el.isolateScope(); @@ -351,19 +414,32 @@ describe('Table Vis - AggTable Directive', function () { const formatted = aggTable.toCsv(true); expect(formatted).to.be( - '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + '\r\n' + - '"png_formatted",IT,win,412032,9299,0' + '\r\n' + - '"png_formatted",IT,mac,412032,9299,9299' + '\r\n' + - '"png_formatted",US,linux,412032,8293,3992' + '\r\n' + - '"png_formatted",US,mac,412032,8293,3029' + '\r\n' + - '"css_formatted",MX,win,412032,9299,4992' + '\r\n' + - '"css_formatted",MX,mac,412032,9299,5892' + '\r\n' + - '"css_formatted",US,linux,412032,8293,3992' + '\r\n' + - '"css_formatted",US,mac,412032,8293,3029' + '\r\n' + - '"html_formatted",CN,win,412032,9299,4992' + '\r\n' + - '"html_formatted",CN,mac,412032,9299,5892' + '\r\n' + - '"html_formatted",FR,win,412032,8293,3992' + '\r\n' + - '"html_formatted",FR,mac,412032,8293,3029' + '\r\n' + '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + + '\r\n' + + '"png_formatted",IT,win,412032,9299,0' + + '\r\n' + + '"png_formatted",IT,mac,412032,9299,9299' + + '\r\n' + + '"png_formatted",US,linux,412032,8293,3992' + + '\r\n' + + '"png_formatted",US,mac,412032,8293,3029' + + '\r\n' + + '"css_formatted",MX,win,412032,9299,4992' + + '\r\n' + + '"css_formatted",MX,mac,412032,9299,5892' + + '\r\n' + + '"css_formatted",US,linux,412032,8293,3992' + + '\r\n' + + '"css_formatted",US,mac,412032,8293,3029' + + '\r\n' + + '"html_formatted",CN,win,412032,9299,4992' + + '\r\n' + + '"html_formatted",CN,mac,412032,9299,5892' + + '\r\n' + + '"html_formatted",FR,win,412032,8293,3992' + + '\r\n' + + '"html_formatted",FR,mac,412032,8293,3029' + + '\r\n' ); }); }); @@ -452,9 +528,7 @@ describe('Table Vis - AggTable Directive', function () { { id: 'b', name: 'two' }, { id: 'c', name: 'with double-quotes(")' }, ], - rows: [ - { a: 1, b: 2, c: '"foobar"' }, - ], + rows: [{ a: 1, b: 2, c: '"foobar"' }], }; aggTable.csv.filename = 'somefilename.csv'; @@ -464,25 +538,26 @@ describe('Table Vis - AggTable Directive', function () { const call = saveAs.getCall(0); expect(call.args[0]).to.be.a(FakeBlob); expect(call.args[0].slices).to.eql([ - 'one,two,"with double-quotes("")"' + '\r\n' + - '1,2,"""foobar"""' + '\r\n' + 'one,two,"with double-quotes("")"' + '\r\n' + '1,2,"""foobar"""' + '\r\n', ]); expect(call.args[0].opts).to.eql({ - type: 'text/plain;charset=utf-8' + type: 'text/plain;charset=utf-8', }); expect(call.args[1]).to.be('somefilename.csv'); }); it('should use the export-title attribute', function () { const expected = 'export file name'; - const $el = $compile(``)($scope); + const $el = $compile( + `` + )($scope); $scope.$digest(); const $tableScope = $el.isolateScope(); const aggTable = $tableScope.aggTable; $tableScope.table = { columns: [], - rows: [] + rows: [], }; $tableScope.exportTitle = expected; $scope.$digest(); diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js index 075a07f0c96b2..77a0ee5221b95 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js @@ -28,7 +28,7 @@ import { tabifyAggResponse } from 'ui/agg_response/tabify'; import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { createTableVisTypeDefinition } from '../../table_vis_type'; -import { visualizations } from '../../../../visualizations/public'; +import { setup as visualizationsSetup } from '../../../../visualizations/public/legacy'; describe('Table Vis - AggTableGroup Directive', function () { let $rootScope; @@ -49,35 +49,35 @@ describe('Table Vis - AggTableGroup Directive', function () { { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, { type: 'terms', schema: 'split', params: { field: 'extension' } }, { type: 'terms', schema: 'segment', params: { field: 'geo.src' } }, - { type: 'terms', schema: 'segment', params: { field: 'machine.os' } } - ] + { type: 'terms', schema: 'segment', params: { field: 'machine.os' } }, + ], }); - vis2.aggs.forEach(function (agg, i) { + vis2.aggs.aggs.forEach(function (agg, i) { agg.id = 'agg_' + (i + 1); }); tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, fixtures.threeTermBuckets); }; beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function ($injector, Private) { - legacyDependencies = { - // eslint-disable-next-line new-cap - createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization - }; + beforeEach( + ngMock.inject(function ($injector, Private) { + legacyDependencies = { + // eslint-disable-next-line new-cap + createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization, + }; - visualizations.types.VisTypesRegistryProvider.register(() => - createTableVisTypeDefinition(legacyDependencies) - ); + visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies)); - tableAggResponse = legacyResponseHandlerProvider().handler; - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - Vis = Private(VisProvider); + tableAggResponse = legacyResponseHandlerProvider().handler; + indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + Vis = Private(VisProvider); - $rootScope = $injector.get('$rootScope'); - $compile = $injector.get('$compile'); + $rootScope = $injector.get('$rootScope'); + $compile = $injector.get('$compile'); - init(); - })); + init(); + }) + ); let $scope; beforeEach(function () { @@ -88,13 +88,18 @@ describe('Table Vis - AggTableGroup Directive', function () { }); it('renders a simple split response properly', async function () { - $scope.dimensions = { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [] }; + $scope.dimensions = { + metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], + buckets: [], + }; $scope.group = await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions); $scope.sort = { columnIndex: null, - direction: null + direction: null, }; - const $el = $(''); + const $el = $( + '' + ); $compile($el)($scope); $scope.$digest(); @@ -104,10 +109,12 @@ describe('Table Vis - AggTableGroup Directive', function () { }); it('renders nothing if the table list is empty', function () { - const $el = $(''); + const $el = $( + '' + ); $scope.group = { - tables: [] + tables: [], }; $compile($el)($scope); @@ -121,10 +128,19 @@ describe('Table Vis - AggTableGroup Directive', function () { $scope.dimensions = { splitRow: [{ accessor: 0, params: {} }], buckets: [{ accessor: 2, params: {} }, { accessor: 4, params: {} }], - metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }] + metrics: [ + { accessor: 1, params: {} }, + { accessor: 3, params: {} }, + { accessor: 5, params: {} }, + ], }; - const group = $scope.group = await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions); - const $el = $(''); + const group = ($scope.group = await tableAggResponse( + tabifiedData.threeTermBuckets, + $scope.dimensions + )); + const $el = $( + '' + ); $compile($el)($scope); $scope.$digest(); diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy.ts b/src/legacy/core_plugins/vis_type_table/public/legacy.ts index fded5690a362d..5ec181f0e6974 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy.ts @@ -22,12 +22,12 @@ import { npSetup, npStart } from 'ui/new_platform'; import { plugin } from '.'; import { TablePluginSetupDependencies } from './plugin'; -import { visualizations } from '../../visualizations/public'; +import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; import { LegacyDependenciesPlugin } from './shim'; const plugins: Readonly = { - visualizations, - data: npSetup.plugins.data, + expressions: npSetup.plugins.expressions, + visualizations: visualizationsSetup, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/vis_type_table/public/plugin.ts b/src/legacy/core_plugins/vis_type_table/public/plugin.ts index 21b6e21d6d639..cc272275fe740 100644 --- a/src/legacy/core_plugins/vis_type_table/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_table/public/plugin.ts @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ +import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; -import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public'; import { PluginInitializerContext, @@ -39,7 +39,7 @@ export interface TableVisualizationDependencies extends LegacyDependenciesPlugin /** @internal */ export interface TablePluginSetupDependencies { - data: ReturnType; + expressions: ReturnType; visualizations: VisualizationsSetup; __LEGACY: LegacyDependenciesPlugin; } @@ -54,16 +54,16 @@ export class TableVisPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { data, visualizations, __LEGACY }: TablePluginSetupDependencies + { expressions, visualizations, __LEGACY }: TablePluginSetupDependencies ) { const visualizationDependencies: Readonly = { uiSettings: core.uiSettings, ...(await __LEGACY.setup()), }; - data.expressions.registerFunction(createTableVisFn); + expressions.registerFunction(createTableVisFn); - visualizations.types.VisTypesRegistryProvider.register(() => + visualizations.types.registerVisualization(() => createTableVisTypeDefinition(visualizationDependencies) ); } diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_params.js b/src/legacy/core_plugins/vis_type_table/public/table_vis_params.js index 6749eec31a139..8e4b113c3bca0 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_params.js +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_params.js @@ -37,7 +37,7 @@ export function TableVisParams() { $scope.percentageColumns = [noCol]; $scope.$watchMulti([ - '[]editorState.aggs', + '[]editorState.aggs.aggs', 'editorState.params.percentageCol', '=editorState.params.dimensions.buckets', '=editorState.params.dimensions.metrics', diff --git a/src/legacy/core_plugins/vis_type_tagcloud/index.ts b/src/legacy/core_plugins/vis_type_tagcloud/index.ts index 57641b9014261..a086a5af0261d 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/index.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const tagCloudPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'tagcloud', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'data'], + require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx index 728e90e1f36ce..9e6a2d1a24a85 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx @@ -23,8 +23,7 @@ import { i18n } from '@kbn/i18n'; import { ValidatedDualRange } from 'ui/validated_range'; import { VisOptionsProps } from 'ui/vis/editors/default'; -import { SelectOption } from '../../../kbn_vislib_vis_types/public/controls/select'; -import { SwitchOption } from '../../../kbn_vislib_vis_types/public/controls/switch'; +import { SelectOption, SwitchOption } from '../../../kbn_vislib_vis_types/public/components'; import { TagCloudVisParams } from '../types'; function TagCloudOptions({ stateParams, setValue, vis }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts index 01b2d99ce509c..f173eff0aef88 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts @@ -20,13 +20,13 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { visualizations } from '../../visualizations/public'; +import { setup as visualizationsSetup } from '../../visualizations/public/legacy'; import { TagCloudPluginSetupDependencies } from './plugin'; import { plugin } from '.'; const plugins: Readonly = { - visualizations, - data: npSetup.plugins.data, + expressions: npSetup.plugins.expressions, + visualizations: visualizationsSetup, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts index e7f633b4af377..bcb210e9ed081 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts @@ -18,7 +18,7 @@ */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; -import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public'; +import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; import { createTagCloudFn } from './tag_cloud_fn'; @@ -26,7 +26,7 @@ import { createTagCloudTypeDefinition } from './tag_cloud_type'; /** @internal */ export interface TagCloudPluginSetupDependencies { - data: ReturnType; + expressions: ReturnType; visualizations: VisualizationsSetup; } @@ -38,9 +38,9 @@ export class TagCloudPlugin implements Plugin { this.initializerContext = initializerContext; } - public setup(core: CoreSetup, { data, visualizations }: TagCloudPluginSetupDependencies) { - data.expressions.registerFunction(createTagCloudFn); - visualizations.types.VisTypesRegistryProvider.register(createTagCloudTypeDefinition); + public setup(core: CoreSetup, { expressions, visualizations }: TagCloudPluginSetupDependencies) { + expressions.registerFunction(createTagCloudFn); + visualizations.types.registerVisualization(createTagCloudTypeDefinition); } public start(core: CoreStart) { diff --git a/src/legacy/core_plugins/metrics/common/__snapshots__/model_options.test.js.snap b/src/legacy/core_plugins/vis_type_timeseries/common/__snapshots__/model_options.test.js.snap similarity index 100% rename from src/legacy/core_plugins/metrics/common/__snapshots__/model_options.test.js.snap rename to src/legacy/core_plugins/vis_type_timeseries/common/__snapshots__/model_options.test.js.snap diff --git a/src/legacy/core_plugins/metrics/common/__tests__/agg_lookup.js b/src/legacy/core_plugins/vis_type_timeseries/common/__tests__/agg_lookup.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/__tests__/agg_lookup.js rename to src/legacy/core_plugins/vis_type_timeseries/common/__tests__/agg_lookup.js diff --git a/src/legacy/core_plugins/metrics/common/__tests__/calculate_label.js b/src/legacy/core_plugins/vis_type_timeseries/common/__tests__/calculate_label.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/__tests__/calculate_label.js rename to src/legacy/core_plugins/vis_type_timeseries/common/__tests__/calculate_label.js diff --git a/src/legacy/core_plugins/vis_type_timeseries/common/agg_lookup.js b/src/legacy/core_plugins/vis_type_timeseries/common/agg_lookup.js new file mode 100644 index 0000000000000..5c23eaee975cc --- /dev/null +++ b/src/legacy/core_plugins/vis_type_timeseries/common/agg_lookup.js @@ -0,0 +1,127 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { i18n } from '@kbn/i18n'; + +export const lookup = { + count: i18n.translate('visTypeTimeseries.aggLookup.countLabel', { defaultMessage: 'Count' }), + calculation: i18n.translate('visTypeTimeseries.aggLookup.calculationLabel', { defaultMessage: 'Calculation' }), + std_deviation: i18n.translate('visTypeTimeseries.aggLookup.deviationLabel', { + defaultMessage: 'Std. Deviation', + }), + variance: i18n.translate('visTypeTimeseries.aggLookup.varianceLabel', { defaultMessage: 'Variance' }), + sum_of_squares: i18n.translate('visTypeTimeseries.aggLookup.sumOfSqLabel', { defaultMessage: 'Sum of Sq.' }), + avg: i18n.translate('visTypeTimeseries.aggLookup.averageLabel', { defaultMessage: 'Average' }), + max: i18n.translate('visTypeTimeseries.aggLookup.maxLabel', { defaultMessage: 'Max' }), + min: i18n.translate('visTypeTimeseries.aggLookup.minLabel', { defaultMessage: 'Min' }), + sum: i18n.translate('visTypeTimeseries.aggLookup.sumLabel', { defaultMessage: 'Sum' }), + percentile: i18n.translate('visTypeTimeseries.aggLookup.percentileLabel', { defaultMessage: 'Percentile' }), + percentile_rank: i18n.translate('visTypeTimeseries.aggLookup.percentileRankLabel', { + defaultMessage: 'Percentile Rank', + }), + cardinality: i18n.translate('visTypeTimeseries.aggLookup.cardinalityLabel', { defaultMessage: 'Cardinality' }), + value_count: i18n.translate('visTypeTimeseries.aggLookup.valueCountLabel', { defaultMessage: 'Value Count' }), + derivative: i18n.translate('visTypeTimeseries.aggLookup.derivativeLabel', { defaultMessage: 'Derivative' }), + cumulative_sum: i18n.translate('visTypeTimeseries.aggLookup.cumulativeSumLabel', { + defaultMessage: 'Cumulative Sum', + }), + moving_average: i18n.translate('visTypeTimeseries.aggLookup.movingAverageLabel', { + defaultMessage: 'Moving Average', + }), + avg_bucket: i18n.translate('visTypeTimeseries.aggLookup.overallAverageLabel', { + defaultMessage: 'Overall Average', + }), + min_bucket: i18n.translate('visTypeTimeseries.aggLookup.overallMinLabel', { defaultMessage: 'Overall Min' }), + max_bucket: i18n.translate('visTypeTimeseries.aggLookup.overallMaxLabel', { defaultMessage: 'Overall Max' }), + sum_bucket: i18n.translate('visTypeTimeseries.aggLookup.overallSumLabel', { defaultMessage: 'Overall Sum' }), + variance_bucket: i18n.translate('visTypeTimeseries.aggLookup.overallVarianceLabel', { + defaultMessage: 'Overall Variance', + }), + sum_of_squares_bucket: i18n.translate('visTypeTimeseries.aggLookup.overallSumOfSqLabel', { + defaultMessage: 'Overall Sum of Sq.', + }), + std_deviation_bucket: i18n.translate('visTypeTimeseries.aggLookup.overallStdDeviationLabel', { + defaultMessage: 'Overall Std. Deviation', + }), + series_agg: i18n.translate('visTypeTimeseries.aggLookup.seriesAggLabel', { defaultMessage: 'Series Agg' }), + math: i18n.translate('visTypeTimeseries.aggLookup.mathLabel', { defaultMessage: 'Math' }), + serial_diff: i18n.translate('visTypeTimeseries.aggLookup.serialDifferenceLabel', { + defaultMessage: 'Serial Difference', + }), + filter_ratio: i18n.translate('visTypeTimeseries.aggLookup.filterRatioLabel', { + defaultMessage: 'Filter Ratio', + }), + positive_only: i18n.translate('visTypeTimeseries.aggLookup.positiveOnlyLabel', { + defaultMessage: 'Positive Only', + }), + static: i18n.translate('visTypeTimeseries.aggLookup.staticValueLabel', { defaultMessage: 'Static Value' }), + top_hit: i18n.translate('visTypeTimeseries.aggLookup.topHitLabel', { defaultMessage: 'Top Hit' }), +}; + +const pipeline = [ + 'calculation', + 'derivative', + 'cumulative_sum', + 'moving_average', + 'avg_bucket', + 'min_bucket', + 'max_bucket', + 'sum_bucket', + 'variance_bucket', + 'sum_of_squares_bucket', + 'std_deviation_bucket', + 'series_agg', + 'math', + 'serial_diff', + 'positive_only', +]; + +const byType = { + _all: lookup, + pipeline: pipeline, + basic: _.omit(lookup, pipeline), + metrics: _.pick(lookup, ['count', 'avg', 'min', 'max', 'sum', 'cardinality', 'value_count']), +}; + +export function isBasicAgg(item) { + return _.includes(Object.keys(byType.basic), item.type); +} + +export function createOptions(type = '_all', siblings = []) { + let aggs = byType[type]; + if (!aggs) aggs = byType._all; + let enablePipelines = siblings.some(isBasicAgg); + if (siblings.length <= 1) enablePipelines = false; + return _(aggs) + .map((label, value) => { + const disabled = _.includes(pipeline, value) ? !enablePipelines : false; + return { + label: disabled + ? i18n.translate('visTypeTimeseries.aggLookup.addPipelineAggDescription', { + defaultMessage: '{label} (use the "+" button to add this pipeline agg)', + values: { label }, + }) + : label, + value, + disabled, + }; + }) + .value(); +} diff --git a/src/legacy/core_plugins/metrics/common/basic_aggs.js b/src/legacy/core_plugins/vis_type_timeseries/common/basic_aggs.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/basic_aggs.js rename to src/legacy/core_plugins/vis_type_timeseries/common/basic_aggs.js diff --git a/src/legacy/core_plugins/vis_type_timeseries/common/calculate_label.js b/src/legacy/core_plugins/vis_type_timeseries/common/calculate_label.js new file mode 100644 index 0000000000000..873b851a10519 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_timeseries/common/calculate_label.js @@ -0,0 +1,107 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { includes, startsWith } from 'lodash'; +import { lookup } from './agg_lookup'; +import { i18n } from '@kbn/i18n'; + +const paths = [ + 'cumulative_sum', + 'derivative', + 'moving_average', + 'avg_bucket', + 'sum_bucket', + 'min_bucket', + 'max_bucket', + 'std_deviation_bucket', + 'variance_bucket', + 'sum_of_squares_bucket', + 'serial_diff', + 'positive_only', +]; + +export function calculateLabel(metric, metrics) { + if (!metric) { + return i18n.translate('visTypeTimeseries.calculateLabel.unknownLabel', { defaultMessage: 'Unknown' }); + } + if (metric.alias) { + return metric.alias; + } + + if (metric.type === 'count') { + return i18n.translate('visTypeTimeseries.calculateLabel.countLabel', { defaultMessage: 'Count' }); + } + if (metric.type === 'calculation') { + return i18n.translate('visTypeTimeseries.calculateLabel.bucketScriptsLabel', { + defaultMessage: 'Bucket Script', + }); + } + if (metric.type === 'math') { + return i18n.translate('visTypeTimeseries.calculateLabel.mathLabel', { defaultMessage: 'Math' }); + } + if (metric.type === 'series_agg') { + return i18n.translate('visTypeTimeseries.calculateLabel.seriesAggLabel', { + defaultMessage: 'Series Agg ({metricFunction})', + values: { metricFunction: metric.function }, + }); + } + if (metric.type === 'filter_ratio') { + return i18n.translate('visTypeTimeseries.calculateLabel.filterRatioLabel', { + defaultMessage: 'Filter Ratio', + }); + } + if (metric.type === 'static') { + return i18n.translate('visTypeTimeseries.calculateLabel.staticValueLabel', { + defaultMessage: 'Static Value of {metricValue}', + values: { metricValue: metric.value }, + }); + } + + if (includes(paths, metric.type)) { + const targetMetric = metrics.find(m => startsWith(metric.field, m.id)); + const targetLabel = calculateLabel(targetMetric, metrics); + + // For percentiles we need to parse the field id to extract the percentile + // the user configured in the percentile aggregation and specified in the + // submetric they selected. This applies only to pipeline aggs. + if (targetMetric && targetMetric.type === 'percentile') { + const percentileValueMatch = /\[([0-9\.]+)\]$/; + const matches = metric.field.match(percentileValueMatch); + if (matches) { + return i18n.translate('visTypeTimeseries.calculateLabel.lookupMetricTypeOfTargetWithAdditionalLabel', { + defaultMessage: '{lookupMetricType} of {targetLabel} ({additionalLabel})', + values: { + lookupMetricType: lookup[metric.type], + targetLabel, + additionalLabel: matches[1], + }, + }); + } + } + return i18n.translate('visTypeTimeseries.calculateLabel.lookupMetricTypeOfTargetLabel', { + defaultMessage: '{lookupMetricType} of {targetLabel}', + values: { lookupMetricType: lookup[metric.type], targetLabel }, + }); + } + + return i18n.translate('visTypeTimeseries.calculateLabel.lookupMetricTypeOfMetricFieldRankLabel', { + defaultMessage: '{lookupMetricType} of {metricField}', + values: { lookupMetricType: lookup[metric.type], metricField: metric.field }, + }); +} diff --git a/src/legacy/core_plugins/metrics/common/es_types.js b/src/legacy/core_plugins/vis_type_timeseries/common/es_types.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/es_types.js rename to src/legacy/core_plugins/vis_type_timeseries/common/es_types.js diff --git a/src/legacy/core_plugins/metrics/common/extract_index_patterns.js b/src/legacy/core_plugins/vis_type_timeseries/common/extract_index_patterns.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/extract_index_patterns.js rename to src/legacy/core_plugins/vis_type_timeseries/common/extract_index_patterns.js diff --git a/src/legacy/core_plugins/metrics/common/extract_index_patterns.test.js b/src/legacy/core_plugins/vis_type_timeseries/common/extract_index_patterns.test.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/extract_index_patterns.test.js rename to src/legacy/core_plugins/vis_type_timeseries/common/extract_index_patterns.test.js diff --git a/src/legacy/core_plugins/metrics/common/field_types.js b/src/legacy/core_plugins/vis_type_timeseries/common/field_types.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/field_types.js rename to src/legacy/core_plugins/vis_type_timeseries/common/field_types.js diff --git a/src/legacy/core_plugins/metrics/common/get_last_value.js b/src/legacy/core_plugins/vis_type_timeseries/common/get_last_value.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/get_last_value.js rename to src/legacy/core_plugins/vis_type_timeseries/common/get_last_value.js diff --git a/src/legacy/core_plugins/metrics/common/get_last_value.test.js b/src/legacy/core_plugins/vis_type_timeseries/common/get_last_value.test.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/get_last_value.test.js rename to src/legacy/core_plugins/vis_type_timeseries/common/get_last_value.test.js diff --git a/src/legacy/core_plugins/metrics/common/interval_regexp.js b/src/legacy/core_plugins/vis_type_timeseries/common/interval_regexp.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/interval_regexp.js rename to src/legacy/core_plugins/vis_type_timeseries/common/interval_regexp.js diff --git a/src/legacy/core_plugins/metrics/common/interval_regexp.test.js b/src/legacy/core_plugins/vis_type_timeseries/common/interval_regexp.test.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/interval_regexp.test.js rename to src/legacy/core_plugins/vis_type_timeseries/common/interval_regexp.test.js diff --git a/src/legacy/core_plugins/metrics/common/metric_types.js b/src/legacy/core_plugins/vis_type_timeseries/common/metric_types.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/metric_types.js rename to src/legacy/core_plugins/vis_type_timeseries/common/metric_types.js diff --git a/src/legacy/core_plugins/metrics/common/model_options.js b/src/legacy/core_plugins/vis_type_timeseries/common/model_options.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/model_options.js rename to src/legacy/core_plugins/vis_type_timeseries/common/model_options.js diff --git a/src/legacy/core_plugins/metrics/common/model_options.test.js b/src/legacy/core_plugins/vis_type_timeseries/common/model_options.test.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/model_options.test.js rename to src/legacy/core_plugins/vis_type_timeseries/common/model_options.test.js diff --git a/src/legacy/core_plugins/metrics/common/panel_types.js b/src/legacy/core_plugins/vis_type_timeseries/common/panel_types.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/panel_types.js rename to src/legacy/core_plugins/vis_type_timeseries/common/panel_types.js diff --git a/src/legacy/core_plugins/metrics/common/set_is_reversed.js b/src/legacy/core_plugins/vis_type_timeseries/common/set_is_reversed.js similarity index 96% rename from src/legacy/core_plugins/metrics/common/set_is_reversed.js rename to src/legacy/core_plugins/vis_type_timeseries/common/set_is_reversed.js index a5faed3d8a4e8..b633d004b9705 100644 --- a/src/legacy/core_plugins/metrics/common/set_is_reversed.js +++ b/src/legacy/core_plugins/vis_type_timeseries/common/set_is_reversed.js @@ -52,7 +52,7 @@ export const isBackgroundDark = (backgroundColor, currentTheme) => { const themeIsDark = isThemeDark(currentTheme); // If a background color doesn't exist or it inherits, pass back if it's a darktheme - if (backgroundColor === undefined || backgroundColor === 'inherit') { + if (!backgroundColor || backgroundColor === 'inherit') { return themeIsDark; } diff --git a/src/legacy/core_plugins/metrics/common/timerange_data_modes.js b/src/legacy/core_plugins/vis_type_timeseries/common/timerange_data_modes.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/timerange_data_modes.js rename to src/legacy/core_plugins/vis_type_timeseries/common/timerange_data_modes.js diff --git a/src/legacy/core_plugins/metrics/common/to_percentile_number.js b/src/legacy/core_plugins/vis_type_timeseries/common/to_percentile_number.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/to_percentile_number.js rename to src/legacy/core_plugins/vis_type_timeseries/common/to_percentile_number.js diff --git a/src/legacy/core_plugins/metrics/common/ui_restrictions.js b/src/legacy/core_plugins/vis_type_timeseries/common/ui_restrictions.js similarity index 100% rename from src/legacy/core_plugins/metrics/common/ui_restrictions.js rename to src/legacy/core_plugins/vis_type_timeseries/common/ui_restrictions.js diff --git a/src/legacy/core_plugins/vis_type_timeseries/index.ts b/src/legacy/core_plugins/vis_type_timeseries/index.ts new file mode 100644 index 0000000000000..f302e36c046c4 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_timeseries/index.ts @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 { Legacy } from 'kibana'; +import { PluginInitializerContext } from 'src/core/server'; +import { CoreSetup } from 'src/core/server'; + +import { plugin } from './server/'; +import { CustomCoreSetup } from './server/plugin'; + +import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy/types'; + +const metricsPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => + new Plugin({ + id: 'metrics', + require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'expressions'], + publicDir: resolve(__dirname, 'public'), + uiExports: { + styleSheetPaths: resolve(__dirname, 'public/index.scss'), + hacks: [resolve(__dirname, 'public/legacy')], + injectDefaultVars: server => ({}), + }, + init: (server: Legacy.Server) => { + const initializerContext = {} as PluginInitializerContext; + const core = { http: { server } } as CoreSetup & CustomCoreSetup; + + plugin(initializerContext).setup(core); + }, + config(Joi: any) { + return Joi.object({ + enabled: Joi.boolean().default(true), + chartResolution: Joi.number().default(150), + minimumBucketSize: Joi.number().default(10), + }).default(); + }, + } as Legacy.PluginSpecOptions); + +// eslint-disable-next-line import/no-default-export +export default metricsPluginInitializer; diff --git a/src/legacy/core_plugins/metrics/package.json b/src/legacy/core_plugins/vis_type_timeseries/package.json similarity index 100% rename from src/legacy/core_plugins/metrics/package.json rename to src/legacy/core_plugins/vis_type_timeseries/package.json diff --git a/src/legacy/core_plugins/metrics/public/_mixins.scss b/src/legacy/core_plugins/vis_type_timeseries/public/_mixins.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/_mixins.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/_mixins.scss diff --git a/src/legacy/core_plugins/metrics/public/_tvb_editor.scss b/src/legacy/core_plugins/vis_type_timeseries/public/_tvb_editor.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/_tvb_editor.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/_tvb_editor.scss diff --git a/src/legacy/core_plugins/metrics/public/_variables.scss b/src/legacy/core_plugins/vis_type_timeseries/public/_variables.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/_variables.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/_variables.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_annotations_editor.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_annotations_editor.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_annotations_editor.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_annotations_editor.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_color_picker.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_color_picker.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_color_picker.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_color_picker.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_color_rules.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_color_rules.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_color_rules.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_color_rules.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_custom_color_picker.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_custom_color_picker.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_custom_color_picker.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_custom_color_picker.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_error.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_error.scss similarity index 95% rename from src/legacy/core_plugins/metrics/public/components/_error.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_error.scss index efe378bb791c2..fdfc747dbeb3e 100644 --- a/src/legacy/core_plugins/metrics/public/components/_error.scss +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/_error.scss @@ -1,16 +1,16 @@ -.tvbError__title, -.tvbError__additional, -.tvbError__stack { - margin-top: $euiSizeS; -} - -// EUITODO: Convert to EuiCodeBlock -.tvbError__stack { - padding: $euiSizeS; - background: $euiCodeBlockBackgroundColor; - color: $euiCodeBlockColor; - line-height: $euiLineHeight; - font-family: $euiCodeFontFamily; - font-weight: $euiFontWeightRegular; - white-space: pre-wrap; -} +.tvbError__title, +.tvbError__additional, +.tvbError__stack { + margin-top: $euiSizeS; +} + +// EUITODO: Convert to EuiCodeBlock +.tvbError__stack { + padding: $euiSizeS; + background: $euiCodeBlockBackgroundColor; + color: $euiCodeBlockColor; + line-height: $euiLineHeight; + font-family: $euiCodeFontFamily; + font-weight: $euiFontWeightRegular; + white-space: pre-wrap; +} diff --git a/src/legacy/core_plugins/metrics/public/components/_index.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_index.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_index.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_index.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_markdown_editor.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_markdown_editor.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_markdown_editor.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_markdown_editor.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_no_data.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_no_data.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_no_data.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_no_data.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_series_editor.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_series_editor.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_series_editor.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_series_editor.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_vis_editor.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_editor.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_vis_editor.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_editor.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_vis_editor_visualization.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_editor_visualization.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_vis_editor_visualization.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_editor_visualization.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_vis_picker.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_picker.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_vis_picker.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_picker.scss diff --git a/src/legacy/core_plugins/metrics/public/components/_vis_with_splits.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_with_splits.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/_vis_with_splits.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/_vis_with_splits.scss diff --git a/src/legacy/core_plugins/metrics/public/components/add_delete_buttons.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/add_delete_buttons.js similarity index 88% rename from src/legacy/core_plugins/metrics/public/components/add_delete_buttons.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/add_delete_buttons.js index 0955bea976b65..5c642d22d42ce 100644 --- a/src/legacy/core_plugins/metrics/public/components/add_delete_buttons.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/add_delete_buttons.js @@ -125,22 +125,22 @@ export function AddDeleteButtons(props) { AddDeleteButtons.defaultProps = { testSubj: 'Add', - activeTooltip: i18n.translate('tsvb.addDeleteButtons.addButtonDefaultTooltip', { + activeTooltip: i18n.translate('visTypeTimeseries.addDeleteButtons.addButtonDefaultTooltip', { defaultMessage: 'Add', }), - addTooltip: i18n.translate('tsvb.addDeleteButtons.addButtonDefaultTooltip', { + addTooltip: i18n.translate('visTypeTimeseries.addDeleteButtons.addButtonDefaultTooltip', { defaultMessage: 'Add', }), - deleteTooltip: i18n.translate('tsvb.addDeleteButtons.deleteButtonDefaultTooltip', { + deleteTooltip: i18n.translate('visTypeTimeseries.addDeleteButtons.deleteButtonDefaultTooltip', { defaultMessage: 'Delete', }), - cloneTooltip: i18n.translate('tsvb.addDeleteButtons.cloneButtonDefaultTooltip', { + cloneTooltip: i18n.translate('visTypeTimeseries.addDeleteButtons.cloneButtonDefaultTooltip', { defaultMessage: 'Clone', }), - activatePanelTooltip: i18n.translate('tsvb.addDeleteButtons.reEnableTooltip', { + activatePanelTooltip: i18n.translate('visTypeTimeseries.addDeleteButtons.reEnableTooltip', { defaultMessage: 'Re-enable', }), - deactivatePanelTooltip: i18n.translate('tsvb.addDeleteButtons.temporarilyDisableTooltip', { + deactivatePanelTooltip: i18n.translate('visTypeTimeseries.addDeleteButtons.temporarilyDisableTooltip', { defaultMessage: 'Temporarily Disable', }), }; diff --git a/src/legacy/core_plugins/metrics/public/components/add_delete_buttons.test.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/add_delete_buttons.test.js similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/add_delete_buttons.test.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/add_delete_buttons.test.js diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/_agg_row.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/_agg_row.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/aggs/_agg_row.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/_agg_row.scss diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/_index.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/_index.scss similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/aggs/_index.scss rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/_index.scss diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/agg.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg.js similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/aggs/agg.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg.js diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/agg_row.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_row.js similarity index 95% rename from src/legacy/core_plugins/metrics/public/components/aggs/agg_row.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_row.js index d7ad87943f8b9..b07e1cef4fc81 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/agg_row.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_row.js @@ -58,11 +58,11 @@ function AggRowUi(props) { { + if (panelType === 'table') return agg.value !== 'series_agg'; + return true; + }; +} + +function AggSelectUi(props) { + const { siblings, panelType, value, onChange, intl, uiRestrictions, ...rest } = props; + + const selectedOptions = allAggOptions.filter(option => { + return value === option.value && isMetricEnabled(option.value, uiRestrictions); + }); + + let enablePipelines = siblings.some(s => !!metricAggs.find(m => m.value === s.type)); + + if (siblings.length <= 1) enablePipelines = false; + + let options; + if (panelType === 'metrics') { + options = metricAggs; + } else { + const disableSiblingAggs = agg => ({ + ...agg, + disabled: !enablePipelines || !isMetricEnabled(agg.value, uiRestrictions), + }); + + options = [ + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.aggSelect.aggGroups.metricAggLabel', + defaultMessage: 'Metric Aggregations', + }), + options: metricAggs.map(agg => ({ + ...agg, + disabled: !isMetricEnabled(agg.value, uiRestrictions), + })), + }, + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.aggSelect.aggGroups.parentPipelineAggLabel', + defaultMessage: 'Parent Pipeline Aggregations', + }), + options: pipelineAggs.filter(filterByPanelType(panelType)).map(disableSiblingAggs), + }, + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.aggSelect.aggGroups.siblingPipelineAggLabel', + defaultMessage: 'Sibling Pipeline Aggregations', + }), + options: siblingAggs.map(disableSiblingAggs), + }, + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.aggSelect.aggGroups.specialAggLabel', + defaultMessage: 'Special Aggregations', + }), + options: specialAggs.map(disableSiblingAggs), + }, + ]; + } + + const handleChange = selectedOptions => { + if (!selectedOptions || selectedOptions.length <= 0) return; + onChange(selectedOptions); + }; + + return ( +
    + +
    + ); +} + +AggSelectUi.propTypes = { + onChange: PropTypes.func, + panelType: PropTypes.string, + siblings: PropTypes.array, + value: PropTypes.string, + uiRestrictions: PropTypes.object, +}; + +export const AggSelect = injectI18n(AggSelectUi); diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/aggs.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/aggs.js similarity index 100% rename from src/legacy/core_plugins/metrics/public/components/aggs/aggs.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/aggs.js diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/calculation.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/calculation.js similarity index 93% rename from src/legacy/core_plugins/metrics/public/components/aggs/calculation.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/calculation.js index 5cdf4dc1c4aa2..bf9b12358094d 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/calculation.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/calculation.js @@ -76,7 +76,7 @@ export class CalculationAgg extends Component { @@ -91,7 +91,7 @@ export class CalculationAgg extends Component { - + } @@ -115,7 +115,7 @@ export class CalculationAgg extends Component { helpText={
    @@ -60,7 +60,7 @@ export function CumulativeSumAgg(props) { } + label={} > { - + { } + label={} fullWidth > { id={htmlId('units')} label={ diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/field_select.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/field_select.js similarity index 97% rename from src/legacy/core_plugins/metrics/public/components/aggs/field_select.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/field_select.js index f1d48ad820156..a4168fd1398f1 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/field_select.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/field_select.js @@ -94,7 +94,7 @@ FieldSelectUi.defaultProps = { indexPattern: '*', disabled: false, restrict: [], - placeholder: i18n.translate('tsvb.fieldSelect.selectFieldPlaceholder', { + placeholder: i18n.translate('visTypeTimeseries.fieldSelect.selectFieldPlaceholder', { defaultMessage: 'Select field...', }), }; diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/filter_ratio.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/filter_ratio.js similarity index 90% rename from src/legacy/core_plugins/metrics/public/components/aggs/filter_ratio.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/filter_ratio.js index f6eab0a565b69..364536cfba6ac 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/filter_ratio.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/filter_ratio.js @@ -70,7 +70,7 @@ export const FilterRatioAgg = props => { - + { + } > @@ -97,7 +97,7 @@ export const FilterRatioAgg = props => { id={htmlId('denominator')} label={ } @@ -113,7 +113,7 @@ export const FilterRatioAgg = props => { @@ -130,7 +130,7 @@ export const FilterRatioAgg = props => { } + label={} > - + - + + } fullWidth helpText={ diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/metric_select.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/metric_select.js similarity index 98% rename from src/legacy/core_plugins/metrics/public/components/aggs/metric_select.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/metric_select.js index a081af20a3ebb..5e2f148ab5a6e 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/metric_select.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/metric_select.js @@ -123,7 +123,7 @@ function MetricSelectUi(props) { return ( { const model = { ...DEFAULTS, ...props.model }; const modelOptions = [ { - label: i18n.translate('tsvb.movingAverage.modelOptions.simpleLabel', { + label: i18n.translate('visTypeTimeseries.movingAverage.modelOptions.simpleLabel', { defaultMessage: 'Simple', }), value: MODEL_TYPES.UNWEIGHTED, }, { - label: i18n.translate('tsvb.movingAverage.modelOptions.linearLabel', { + label: i18n.translate('visTypeTimeseries.movingAverage.modelOptions.linearLabel', { defaultMessage: 'Linear', }), value: MODEL_TYPES.WEIGHTED_LINEAR, }, { - label: i18n.translate('tsvb.movingAverage.modelOptions.exponentiallyWeightedLabel', { + label: i18n.translate('visTypeTimeseries.movingAverage.modelOptions.exponentiallyWeightedLabel', { defaultMessage: 'Exponentially Weighted', }), value: MODEL_TYPES.WEIGHTED_EXPONENTIAL, }, { - label: i18n.translate('tsvb.movingAverage.modelOptions.holtLinearLabel', { + label: i18n.translate('visTypeTimeseries.movingAverage.modelOptions.holtLinearLabel', { defaultMessage: 'Holt-Linear', }), value: MODEL_TYPES.WEIGHTED_EXPONENTIAL_DOUBLE, }, { - label: i18n.translate('tsvb.movingAverage.modelOptions.holtWintersLabel', { + label: i18n.translate('visTypeTimeseries.movingAverage.modelOptions.holtWintersLabel', { defaultMessage: 'Holt-Winters', }), value: MODEL_TYPES.WEIGHTED_EXPONENTIAL_TRIPLE, @@ -97,13 +97,13 @@ export const MovingAverageAgg = props => { const multiplicativeOptions = [ { - label: i18n.translate('tsvb.movingAverage.multiplicativeOptions.true', { + label: i18n.translate('visTypeTimeseries.movingAverage.multiplicativeOptions.true', { defaultMessage: 'True', }), value: true, }, { - label: i18n.translate('tsvb.movingAverage.multiplicativeOptions.false', { + label: i18n.translate('visTypeTimeseries.movingAverage.multiplicativeOptions.false', { defaultMessage: 'False', }), value: false, @@ -125,7 +125,7 @@ export const MovingAverageAgg = props => { - {i18n.translate('tsvb.movingAverage.aggregationLabel', { + {i18n.translate('visTypeTimeseries.movingAverage.aggregationLabel', { defaultMessage: 'Aggregation', })} @@ -140,7 +140,7 @@ export const MovingAverageAgg = props => { @@ -160,13 +160,13 @@ export const MovingAverageAgg = props => { { { @@ -231,7 +231,7 @@ export const MovingAverageAgg = props => { @@ -248,7 +248,7 @@ export const MovingAverageAgg = props => { @@ -262,7 +262,7 @@ export const MovingAverageAgg = props => { @@ -276,13 +276,13 @@ export const MovingAverageAgg = props => { @@ -89,7 +89,7 @@ export class PercentileAgg extends Component { } + label={} > - + diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/percentile_rank/percentile_rank.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/percentile_rank/percentile_rank.js similarity index 95% rename from src/legacy/core_plugins/metrics/public/components/aggs/percentile_rank/percentile_rank.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/percentile_rank/percentile_rank.js index 08be4a8e67739..bc5facaeded2c 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/percentile_rank/percentile_rank.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/percentile_rank/percentile_rank.js @@ -73,7 +73,7 @@ export const PercentileRankAgg = props => { @@ -88,7 +88,7 @@ export const PercentileRankAgg = props => { } + label={} > - + @@ -123,7 +123,7 @@ class PercentilesUi extends Component { - + @@ -137,7 +137,7 @@ class PercentilesUi extends Component { - + diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/positive_only.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/positive_only.js similarity index 94% rename from src/legacy/core_plugins/metrics/public/components/aggs/positive_only.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/positive_only.js index aedecbc2e9e7d..2343741dac9f3 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/positive_only.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/positive_only.js @@ -50,7 +50,7 @@ export const PositiveOnlyAgg = props => { @@ -65,7 +65,7 @@ export const PositiveOnlyAgg = props => { } + label={} > { - + { } + label={} > { id={htmlId('lag')} label={ { + return model.function === option.value; + }); + + if (panel.type === 'table') { + return ( + + + + + + + + ); + } + + return ( + + + + + + + + + + } + > + + + + + + ); +} + +SeriesAggUi.propTypes = { + disableDelete: PropTypes.bool, + fields: PropTypes.object, + model: PropTypes.object, + onAdd: PropTypes.func, + onChange: PropTypes.func, + onDelete: PropTypes.func, + panel: PropTypes.object, + series: PropTypes.object, + siblings: PropTypes.array, +}; + +export const SeriesAgg = injectI18n(SeriesAggUi); diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/static.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/static.js similarity index 93% rename from src/legacy/core_plugins/metrics/public/components/aggs/static.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/static.js index bdf834dd76c70..de83a118a5fdd 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/static.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/static.js @@ -61,7 +61,7 @@ export const Static = props => { - + { + } > - + } + label={} fullWidth > { const modeOptions = [ { label: intl.formatMessage({ - id: 'tsvb.stdDeviation.modeOptions.rawLabel', + id: 'visTypeTimeseries.stdDeviation.modeOptions.rawLabel', defaultMessage: 'Raw', }), value: 'raw', }, { label: intl.formatMessage({ - id: 'tsvb.stdDeviation.modeOptions.upperBoundLabel', + id: 'visTypeTimeseries.stdDeviation.modeOptions.upperBoundLabel', defaultMessage: 'Upper Bound', }), value: 'upper', }, { label: intl.formatMessage({ - id: 'tsvb.stdDeviation.modeOptions.lowerBoundLabel', + id: 'visTypeTimeseries.stdDeviation.modeOptions.lowerBoundLabel', defaultMessage: 'Lower Bound', }), value: 'lower', @@ -71,7 +71,7 @@ const StandardDeviationAggUi = props => { if (panel.type !== 'table') { modeOptions.push({ label: intl.formatMessage({ - id: 'tsvb.stdDeviation.modeOptions.boundsBandLabel', + id: 'visTypeTimeseries.stdDeviation.modeOptions.boundsBandLabel', defaultMessage: 'Bounds Band', }), value: 'band', @@ -102,7 +102,7 @@ const StandardDeviationAggUi = props => { @@ -117,7 +117,7 @@ const StandardDeviationAggUi = props => { } + label={} > { } + label={} > @@ -140,7 +140,7 @@ const StandardDeviationAggUi = props => { } + label={} > { + const { siblings, intl } = props; + const defaults = { sigma: '' }; + const model = { ...defaults, ...props.model }; + const htmlId = htmlIdGenerator(); + + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + const handleTextChange = createTextHandler(handleChange); + + const stdDev = {}; + if (model.type === 'std_deviation_bucket') { + stdDev.sigma = ( + + } + > + + + + ); + + const modeOptions = [ + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.stdSibling.modeOptions.rawLabel', + defaultMessage: 'Raw', + }), + value: 'raw', + }, + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.stdSibling.modeOptions.upperBoundLabel', + defaultMessage: 'Upper Bound', + }), + value: 'upper', + }, + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.stdSibling.modeOptions.lowerBoundLabel', + defaultMessage: 'Lower Bound', + }), + value: 'lower', + }, + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.stdSibling.modeOptions.boundsBandLabel', + defaultMessage: 'Bounds Band', + }), + value: 'band', + }, + ]; + const selectedModeOption = modeOptions.find(option => { + return model.mode === option.value; + }); + + stdDev.mode = ( + + } + > + + + + ); + } + + return ( + + + + + + + + + + } + > + + + + {stdDev.sigma} + {stdDev.mode} + + + ); +}; + +StandardSiblingAggUi.propTypes = { + disableDelete: PropTypes.bool, + fields: PropTypes.object, + model: PropTypes.object, + onAdd: PropTypes.func, + onChange: PropTypes.func, + onDelete: PropTypes.func, + panel: PropTypes.object, + series: PropTypes.object, + siblings: PropTypes.array, + uiRestrictions: PropTypes.object, +}; + +export const StandardSiblingAgg = injectI18n(StandardSiblingAggUi); diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/temporary_unsupported_agg.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/temporary_unsupported_agg.js similarity index 94% rename from src/legacy/core_plugins/metrics/public/components/aggs/temporary_unsupported_agg.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/temporary_unsupported_agg.js index c35956b1c053f..bae0491d978a2 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/temporary_unsupported_agg.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/temporary_unsupported_agg.js @@ -35,7 +35,7 @@ export function TemporaryUnsupportedAgg(props) { {props.model.type} }} /> diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/top_hit.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/top_hit.js similarity index 83% rename from src/legacy/core_plugins/metrics/public/components/aggs/top_hit.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/top_hit.js index 4d823feb40f25..7ec1054927a63 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/top_hit.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/top_hit.js @@ -47,25 +47,25 @@ const getAggWithOptions = (field = {}, fieldTypesRestriction) => { case ES_TYPES.NUMBER: return [ { - label: i18n.translate('tsvb.topHit.aggWithOptions.averageLabel', { + label: i18n.translate('visTypeTimeseries.topHit.aggWithOptions.averageLabel', { defaultMessage: 'Avg', }), value: 'avg', }, { - label: i18n.translate('tsvb.topHit.aggWithOptions.maxLabel', { + label: i18n.translate('visTypeTimeseries.topHit.aggWithOptions.maxLabel', { defaultMessage: 'Max', }), value: 'max', }, { - label: i18n.translate('tsvb.topHit.aggWithOptions.minLabel', { + label: i18n.translate('visTypeTimeseries.topHit.aggWithOptions.minLabel', { defaultMessage: 'Min', }), value: 'min', }, { - label: i18n.translate('tsvb.topHit.aggWithOptions.sumLabel', { + label: i18n.translate('visTypeTimeseries.topHit.aggWithOptions.sumLabel', { defaultMessage: 'Sum', }), value: 'sum', @@ -75,7 +75,7 @@ const getAggWithOptions = (field = {}, fieldTypesRestriction) => { case ES_TYPES.STRING: return [ { - label: i18n.translate('tsvb.topHit.aggWithOptions.concatenate', { + label: i18n.translate('visTypeTimeseries.topHit.aggWithOptions.concatenate', { defaultMessage: 'Concatenate', }), value: 'concat', @@ -89,13 +89,13 @@ const getAggWithOptions = (field = {}, fieldTypesRestriction) => { const getOrderOptions = () => [ { - label: i18n.translate('tsvb.topHit.orderOptions.ascLabel', { + label: i18n.translate('visTypeTimeseries.topHit.orderOptions.ascLabel', { defaultMessage: 'Asc', }), value: 'asc', }, { - label: i18n.translate('tsvb.topHit.orderOptions.descLabel', { + label: i18n.translate('visTypeTimeseries.topHit.orderOptions.descLabel', { defaultMessage: 'Desc', }), value: 'desc', @@ -153,7 +153,7 @@ const TopHitAggUi = props => { - + { } + label={} > { } + label={} > {/* EUITODO: The following input couldn't be converted to EUI because of type mis-match. @@ -204,14 +204,14 @@ const TopHitAggUi = props => { id={htmlId('agg_with')} label={ } > { } + label={} > { } + label={} > {props.model.type} }} /> diff --git a/src/legacy/core_plugins/metrics/public/components/aggs/vars.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/vars.js similarity index 96% rename from src/legacy/core_plugins/metrics/public/components/aggs/vars.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/vars.js index f2497ac0290c2..8553f08af1353 100644 --- a/src/legacy/core_plugins/metrics/public/components/aggs/vars.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/vars.js @@ -52,11 +52,11 @@ class CalculationVarsUi extends Component { } @@ -138,7 +137,7 @@ export class AnnotationsEditor extends Component { id={htmlId('timeField')} label={ } @@ -164,7 +163,7 @@ export class AnnotationsEditor extends Component { id={htmlId('queryString')} label={ } @@ -183,7 +182,7 @@ export class AnnotationsEditor extends Component { @@ -197,7 +196,7 @@ export class AnnotationsEditor extends Component { @@ -218,7 +217,7 @@ export class AnnotationsEditor extends Component { id={htmlId('icon')} label={ } @@ -231,7 +230,7 @@ export class AnnotationsEditor extends Component { id={htmlId('fields')} label={ } @@ -249,14 +248,14 @@ export class AnnotationsEditor extends Component { id={htmlId('rowTemplate')} label={ } helpText={ {'{{field}}'} }} /> @@ -296,13 +295,13 @@ export class AnnotationsEditor extends Component {

    @@ -315,7 +314,7 @@ export class AnnotationsEditor extends Component { diff --git a/src/legacy/core_plugins/metrics/public/components/color_picker.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/color_picker.js similarity index 92% rename from src/legacy/core_plugins/metrics/public/components/color_picker.js rename to src/legacy/core_plugins/vis_type_timeseries/public/components/color_picker.js index 06868a73c6c82..243c7e7db302e 100644 --- a/src/legacy/core_plugins/metrics/public/components/color_picker.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/color_picker.js @@ -60,7 +60,7 @@ export class ColorPicker extends Component { if (!this.props.value) { return (