diff --git a/.github/workflows/airflow-plugin.yml b/.github/workflows/airflow-plugin.yml new file mode 100644 index 00000000000000..63bab821cc398b --- /dev/null +++ b/.github/workflows/airflow-plugin.yml @@ -0,0 +1,85 @@ +name: Airflow Plugin +on: + push: + branches: + - master + paths: + - ".github/workflows/airflow-plugin.yml" + - "metadata-ingestion-modules/airflow-plugin/**" + - "metadata-ingestion/**" + - "metadata-models/**" + pull_request: + branches: + - master + paths: + - ".github/**" + - "metadata-ingestion-modules/airflow-plugin/**" + - "metadata-ingestion/**" + - "metadata-models/**" + release: + types: [published] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + airflow-plugin: + runs-on: ubuntu-latest + env: + SPARK_VERSION: 3.0.3 + DATAHUB_TELEMETRY_ENABLED: false + strategy: + matrix: + include: + - python-version: "3.7" + extraPythonRequirement: "apache-airflow~=2.1.0" + - python-version: "3.7" + extraPythonRequirement: "apache-airflow~=2.2.0" + - python-version: "3.10" + extraPythonRequirement: "apache-airflow~=2.4.0" + - python-version: "3.10" + extraPythonRequirement: "apache-airflow~=2.6.0" + - python-version: "3.10" + extraPythonRequirement: "apache-airflow>2.6.0" + fail-fast: false + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: "pip" + - name: Install dependencies + run: ./metadata-ingestion/scripts/install_deps.sh + - name: Install airflow package and test (extras ${{ matrix.extraPythonRequirement }}) + run: ./gradlew -Pextra_pip_requirements='${{ matrix.extraPythonRequirement }}' :metadata-ingestion-modules:airflow-plugin:lint :metadata-ingestion-modules:airflow-plugin:testQuick + - name: pip freeze show list installed + if: always() + run: source metadata-ingestion-modules/airflow-plugin/venv/bin/activate && pip freeze + - uses: actions/upload-artifact@v3 + if: ${{ always() && matrix.python-version == '3.10' && matrix.extraPythonRequirement == 'apache-airflow>2.6.0' }} + with: + name: Test Results (Airflow Plugin ${{ matrix.python-version}}) + path: | + **/build/reports/tests/test/** + **/build/test-results/test/** + **/junit.*.xml + - name: Upload coverage to Codecov + if: always() + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + directory: . + fail_ci_if_error: false + flags: airflow-${{ matrix.python-version }}-${{ matrix.extraPythonRequirement }} + name: pytest-airflow + verbose: true + + event-file: + runs-on: ubuntu-latest + steps: + - name: Upload + uses: actions/upload-artifact@v3 + with: + name: Event File + path: ${{ github.event_path }} diff --git a/.github/workflows/check-datahub-jars.yml b/.github/workflows/check-datahub-jars.yml index 735ea1e56b169f..841a9ed5f9bc73 100644 --- a/.github/workflows/check-datahub-jars.yml +++ b/.github/workflows/check-datahub-jars.yml @@ -46,7 +46,7 @@ jobs: java-version: 11 - uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.10" - name: check ${{ matrix.command }} jar run: | ./gradlew :metadata-integration:java:${{ matrix.command }}:build --info diff --git a/.github/workflows/docker-ingestion-smoke.yml b/.github/workflows/docker-ingestion-smoke.yml index 9e74f3a459378a..8d52c237928577 100644 --- a/.github/workflows/docker-ingestion-smoke.yml +++ b/.github/workflows/docker-ingestion-smoke.yml @@ -3,8 +3,6 @@ on: release: types: [published] push: - branches: - - master paths: - "docker/datahub-ingestion-base/**" - "smoke-test/**" diff --git a/.github/workflows/docker-unified.yml b/.github/workflows/docker-unified.yml index e8e12ac6def94b..13c921e953c324 100644 --- a/.github/workflows/docker-unified.yml +++ b/.github/workflows/docker-unified.yml @@ -45,6 +45,7 @@ jobs: unique_slim_tag: ${{ steps.tag.outputs.unique_slim_tag }} unique_full_tag: ${{ steps.tag.outputs.unique_full_tag }} publish: ${{ steps.publish.outputs.publish }} + python_release_version: ${{ steps.tag.outputs.python_release_version }} steps: - name: Checkout uses: actions/checkout@v3 @@ -58,6 +59,7 @@ jobs: echo "unique_tag=$(get_unique_tag)" >> $GITHUB_OUTPUT echo "unique_slim_tag=$(get_unique_tag)-slim" >> $GITHUB_OUTPUT echo "unique_full_tag=$(get_unique_tag)-full" >> $GITHUB_OUTPUT + echo "python_release_version=$(get_python_docker_release_v)" >> $GITHUB_OUTPUT - name: Check whether publishing enabled id: publish env: @@ -549,6 +551,7 @@ jobs: runs-on: ubuntu-latest outputs: tag: ${{ steps.tag.outputs.tag }} + needs_artifact_download: ${{ (steps.filter.outputs.datahub-ingestion-base == 'true' || steps.filter.outputs.datahub-ingestion == 'true') && needs.setup.outputs.publish != 'true' }} needs: [setup, datahub_ingestion_base_slim_build] steps: - name: Check out the repo @@ -572,7 +575,7 @@ jobs: with: image: ${{ env.DATAHUB_INGESTION_BASE_IMAGE }}:${{ steps.filter.outputs.datahub-ingestion-base == 'true' && needs.setup.outputs.unique_slim_tag || 'head' }} - name: Build and push Slim Image - if: ${{ steps.filter.outputs.datahub-ingestion-base == 'true' || steps.filter.outputs.datahub-ingestion == 'true' }} + if: ${{ steps.filter.outputs.datahub-ingestion-base == 'true' || steps.filter.outputs.datahub-ingestion == 'true' || needs.setup.outputs.publish }} uses: ./.github/actions/docker-custom-build-and-push with: target: final @@ -581,6 +584,7 @@ jobs: build-args: | BASE_IMAGE=${{ env.DATAHUB_INGESTION_BASE_IMAGE }} DOCKER_VERSION=${{ steps.filter.outputs.datahub-ingestion-base == 'true' && needs.setup.outputs.unique_slim_tag || 'head' }} + RELEASE_VERSION=${{ needs.setup.outputs.python_release_version }} APP_ENV=slim tags: ${{ needs.setup.outputs.slim_tag }} username: ${{ secrets.ACRYL_DOCKER_USERNAME }} @@ -605,7 +609,7 @@ jobs: uses: actions/checkout@v3 - name: Download image Slim Image uses: ishworkh/docker-image-artifact-download@v1 - if: ${{ needs.setup.outputs.publish != 'true' }} + if: ${{ needs.datahub_ingestion_slim_build.outputs.needs_artifact_download == 'true' }} with: image: ${{ env.DATAHUB_INGESTION_IMAGE }}:${{ needs.datahub_ingestion_slim_build.outputs.tag }} - name: Run Trivy vulnerability scanner Slim Image @@ -630,6 +634,7 @@ jobs: runs-on: ubuntu-latest outputs: tag: ${{ steps.tag.outputs.tag }} + needs_artifact_download: ${{ (steps.filter.outputs.datahub-ingestion-base == 'true' || steps.filter.outputs.datahub-ingestion == 'true') && needs.setup.outputs.publish != 'true' }} needs: [setup, datahub_ingestion_base_full_build] steps: - name: Check out the repo @@ -653,7 +658,7 @@ jobs: with: image: ${{ env.DATAHUB_INGESTION_BASE_IMAGE }}:${{ steps.filter.outputs.datahub-ingestion-base == 'true' && needs.setup.outputs.unique_full_tag || 'head' }} - name: Build and push Full Image - if: ${{ steps.filter.outputs.datahub-ingestion-base == 'true' || steps.filter.outputs.datahub-ingestion == 'true' }} + if: ${{ steps.filter.outputs.datahub-ingestion-base == 'true' || steps.filter.outputs.datahub-ingestion == 'true' || needs.setup.outputs.publish }} uses: ./.github/actions/docker-custom-build-and-push with: target: final @@ -662,6 +667,7 @@ jobs: build-args: | BASE_IMAGE=${{ env.DATAHUB_INGESTION_BASE_IMAGE }} DOCKER_VERSION=${{ steps.filter.outputs.datahub-ingestion-base == 'true' && needs.setup.outputs.unique_full_tag || 'head' }} + RELEASE_VERSION=${{ needs.setup.outputs.python_release_version }} tags: ${{ needs.setup.outputs.unique_full_tag }} username: ${{ secrets.ACRYL_DOCKER_USERNAME }} password: ${{ secrets.ACRYL_DOCKER_PASSWORD }} @@ -671,7 +677,7 @@ jobs: platforms: linux/amd64,linux/arm64/v8 - name: Compute Tag (Full) id: tag - run: echo "tag=${{ steps.filter.outputs.datahub-ingestion-base == 'true' && needs.setup.outputs.unique_full_tag || 'head' }}" >> $GITHUB_OUTPUT + run: echo "tag=${{ (steps.filter.outputs.datahub-ingestion-base == 'true' || steps.filter.outputs.datahub-ingestion == 'true') && needs.setup.outputs.unique_full_tag || 'head' }}" >> $GITHUB_OUTPUT datahub_ingestion_full_scan: permissions: contents: read # for actions/checkout to fetch code @@ -685,7 +691,7 @@ jobs: uses: actions/checkout@v3 - name: Download image Full Image uses: ishworkh/docker-image-artifact-download@v1 - if: ${{ needs.setup.outputs.publish != 'true' }} + if: ${{ needs.datahub_ingestion_full_build.outputs.needs_artifact_download == 'true' }} with: image: ${{ env.DATAHUB_INGESTION_IMAGE }}:${{ needs.datahub_ingestion_full_build.outputs.tag }} - name: Run Trivy vulnerability scanner Full Image @@ -737,7 +743,7 @@ jobs: java-version: 11 - uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.10" cache: "pip" - name: Install dependencies run: ./metadata-ingestion/scripts/install_deps.sh @@ -792,7 +798,7 @@ jobs: image: ${{ env.DATAHUB_UPGRADE_IMAGE }}:${{ needs.setup.outputs.unique_tag }} - name: Download datahub-ingestion-slim image uses: ishworkh/docker-image-artifact-download@v1 - if: ${{ needs.setup.outputs.publish != 'true' }} + if: ${{ needs.datahub_ingestion_slim_build.outputs.needs_artifact_download == 'true' }} with: image: ${{ env.DATAHUB_INGESTION_IMAGE }}:${{ needs.datahub_ingestion_slim_build.outputs.tag }} - name: Disk Check @@ -803,7 +809,7 @@ jobs: DATAHUB_VERSION: ${{ needs.setup.outputs.unique_tag }} DATAHUB_ACTIONS_IMAGE: ${{ env.DATAHUB_INGESTION_IMAGE }} ACTIONS_VERSION: ${{ needs.datahub_ingestion_slim_build.outputs.tag }} - ACTIONS_EXTRA_PACKAGES: 'acryl-datahub-actions[executor] acryl-datahub-actions' + ACTIONS_EXTRA_PACKAGES: 'acryl-datahub-actions[executor]==0.0.13 acryl-datahub-actions==0.0.13 acryl-datahub==0.10.5' ACTIONS_CONFIG: 'https://raw.githubusercontent.com/acryldata/datahub-actions/main/docker/config/executor.yaml' run: | ./smoke-test/run-quickstart.sh diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 1cbc65f2b63700..68432a4feb13dd 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -27,6 +27,7 @@ jobs: - uses: actions/setup-python@v4 with: python-version: "3.10" + cache: pip - name: Install Python dependencies run: ./metadata-ingestion/scripts/install_deps.sh - name: Build Docs diff --git a/.github/workflows/metadata-ingestion.yml b/.github/workflows/metadata-ingestion.yml index 23d7ee9427f427..fff41e481c3cb0 100644 --- a/.github/workflows/metadata-ingestion.yml +++ b/.github/workflows/metadata-ingestion.yml @@ -25,7 +25,7 @@ jobs: metadata-ingestion: runs-on: ubuntu-latest env: - SPARK_VERSION: 3.0.3 + SPARK_VERSION: 3.3.2 DATAHUB_TELEMETRY_ENABLED: false # TODO: Enable this once the test is fixed. # DATAHUB_LOOKML_GIT_TEST_SSH_KEY: ${{ secrets.DATAHUB_LOOKML_GIT_TEST_SSH_KEY }} @@ -42,9 +42,7 @@ jobs: ] include: - python-version: "3.7" - extraPythonRequirement: "sqlalchemy==1.3.24 apache-airflow~=2.2.0" - python-version: "3.10" - extraPythonRequirement: "sqlalchemy~=1.4.0 apache-airflow>=2.4.0" fail-fast: false steps: - uses: actions/checkout@v3 @@ -56,8 +54,8 @@ jobs: run: ./metadata-ingestion/scripts/install_deps.sh - name: Install package run: ./gradlew :metadata-ingestion:installPackageOnly - - name: Run metadata-ingestion tests (extras ${{ matrix.extraPythonRequirement }}) - run: ./gradlew -Pextra_pip_requirements='${{ matrix.extraPythonRequirement }}' :metadata-ingestion:${{ matrix.command }} + - name: Run metadata-ingestion tests + run: ./gradlew :metadata-ingestion:${{ matrix.command }} - name: pip freeze show list installed if: always() run: source metadata-ingestion/venv/bin/activate && pip freeze @@ -80,7 +78,6 @@ jobs: name: pytest-${{ matrix.command }} verbose: true - event-file: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/metadata-io.yml b/.github/workflows/metadata-io.yml index 473a73adba9a23..e37ddd0ce4e86f 100644 --- a/.github/workflows/metadata-io.yml +++ b/.github/workflows/metadata-io.yml @@ -36,7 +36,7 @@ jobs: java-version: 11 - uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.10" - name: Gradle build (and test) # there is some race condition in gradle build, which makes gradle never terminate in ~30% of the runs # running build first without datahub-web-react:yarnBuild and then with it is 100% stable diff --git a/.github/workflows/publish-datahub-jars.yml b/.github/workflows/publish-datahub-jars.yml index 1a1523e8db1a10..7cd07b130dd800 100644 --- a/.github/workflows/publish-datahub-jars.yml +++ b/.github/workflows/publish-datahub-jars.yml @@ -58,7 +58,7 @@ jobs: java-version: 11 - uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.10" - name: checkout upstream repo run: | git remote add upstream https://github.com/datahub-project/datahub.git diff --git a/.github/workflows/spark-smoke-test.yml b/.github/workflows/spark-smoke-test.yml index 5f501780873f6f..b2482602e75480 100644 --- a/.github/workflows/spark-smoke-test.yml +++ b/.github/workflows/spark-smoke-test.yml @@ -30,6 +30,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + fetch-depth: 800 + fetch-tags: true - name: Set up JDK 11 uses: actions/setup-java@v3 with: @@ -37,9 +40,11 @@ jobs: java-version: 11 - uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.10" - name: Install dependencies run: ./metadata-ingestion/scripts/install_deps.sh + - name: Remove images + run: docker image prune -a -f || true - name: Smoke test run: | ./gradlew :metadata-integration:java:spark-lineage:integrationTest \ diff --git a/.github/workflows/test-results.yml b/.github/workflows/test-results.yml index 656e4dcbc4e43c..0153060692271c 100644 --- a/.github/workflows/test-results.yml +++ b/.github/workflows/test-results.yml @@ -2,7 +2,7 @@ name: Test Results on: workflow_run: - workflows: ["build & test", "metadata ingestion"] + workflows: ["build & test", "metadata ingestion", "Airflow Plugin"] types: - completed diff --git a/.gitignore b/.gitignore index 858f560f0b8429..49ab5c475096c9 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,8 @@ metadata-ingestion/generated/** # docs docs/generated/ +docs-website/versioned_docs/ +docs-website/versioned_sidebars/ tmp* temp/** diff --git a/README.md b/README.md index d2208cf6ced490..79f85433fbc184 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ export const Logo = (props) => {
DataHub Logo
@@ -18,7 +18,7 @@ export const Logo = (props) => {

-DataHub +DataHub

@@ -80,7 +80,11 @@ Please follow the [DataHub Quickstart Guide](https://datahubproject.io/docs/quic If you're looking to build & modify datahub please take a look at our [Development Guide](https://datahubproject.io/docs/developers). -[![DataHub Demo GIF](docs/imgs/entity.png)](https://demo.datahubproject.io/) +

+ + + +

## Source Code and Repositories @@ -152,7 +156,7 @@ Here are the companies that have officially adopted DataHub. Please feel free to - [DataHub Blog](https://blog.datahubproject.io/) - [DataHub YouTube Channel](https://www.youtube.com/channel/UC3qFQC5IiwR5fvWEqi_tJ5w) -- [Optum: Data Mesh via DataHub](https://optum.github.io/blog/2022/03/23/data-mesh-via-datahub/) +- [Optum: Data Mesh via DataHub](https://opensource.optum.com/blog/2022/03/23/data-mesh-via-datahub) - [Saxo Bank: Enabling Data Discovery in Data Mesh](https://medium.com/datahub-project/enabling-data-discovery-in-a-data-mesh-the-saxo-journey-451b06969c8f) - [Bringing The Power Of The DataHub Real-Time Metadata Graph To Everyone At Acryl Data](https://www.dataengineeringpodcast.com/acryl-data-datahub-metadata-graph-episode-230/) - [DataHub: Popular Metadata Architectures Explained](https://engineering.linkedin.com/blog/2020/datahub-popular-metadata-architectures-explained) diff --git a/build.gradle b/build.gradle index ae54de07cb81c7..1b6b82d51c2d4a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ buildscript { ext.junitJupiterVersion = '5.6.1' // Releases: https://github.com/linkedin/rest.li/blob/master/CHANGELOG.md - ext.pegasusVersion = '29.22.16' + ext.pegasusVersion = '29.45.0' ext.mavenVersion = '3.6.3' ext.springVersion = '5.3.29' ext.springBootVersion = '2.7.14' @@ -9,8 +9,7 @@ buildscript { ext.neo4jVersion = '4.4.9' ext.testContainersVersion = '1.17.4' ext.elasticsearchVersion = '7.10.2' - // TODO: Change to final release version once it's out ETA Mid-April - ext.jacksonVersion = '2.15.0-rc2' + ext.jacksonVersion = '2.15.2' ext.jettyVersion = '9.4.46.v20220331' ext.playVersion = '2.8.18' ext.log4jVersion = '2.19.0' @@ -19,6 +18,7 @@ buildscript { ext.hadoop3Version = '3.3.5' ext.kafkaVersion = '2.3.0' ext.hazelcastVersion = '5.3.1' + ext.ebeanVersion = '12.16.1' ext.docker_registry = 'linkedin' @@ -30,16 +30,16 @@ buildscript { classpath 'io.acryl.gradle.plugin:gradle-avro-plugin:0.8.1' classpath 'org.springframework.boot:spring-boot-gradle-plugin:' + springBootVersion classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.30.0" - classpath "com.palantir.gradle.gitversion:gradle-git-version:0.12.3" - classpath "org.gradle.playframework:gradle-playframework:0.12" - classpath "gradle.plugin.org.hidetake:gradle-swagger-generator-plugin:2.18.1" + classpath "com.palantir.gradle.gitversion:gradle-git-version:3.0.0" + classpath "org.gradle.playframework:gradle-playframework:0.14" + classpath "gradle.plugin.org.hidetake:gradle-swagger-generator-plugin:2.19.1" } } plugins { id 'com.gorylenko.gradle-git-properties' version '2.4.0-rc2' id 'com.github.johnrengelman.shadow' version '6.1.0' - id "com.palantir.docker" version "0.35.0" + id 'com.palantir.docker' version '0.35.0' // https://blog.ltgt.net/javax-jakarta-mess-and-gradle-solution/ // TODO id "org.gradlex.java-ecosystem-capabilities" version "1.0" } @@ -87,8 +87,9 @@ project.ext.externalDependency = [ 'dgraph4j' : 'io.dgraph:dgraph4j:21.03.1', 'dropwizardMetricsCore': 'io.dropwizard.metrics:metrics-core:4.2.3', 'dropwizardMetricsJmx': 'io.dropwizard.metrics:metrics-jmx:4.2.3', - 'ebean': 'io.ebean:ebean:11.33.3', - 'ebeanAgent': 'io.ebean:ebean-agent:11.27.1', + 'ebean': 'io.ebean:ebean:' + ebeanVersion, + 'ebeanAgent': 'io.ebean:ebean-agent:' + ebeanVersion, + 'ebeanDdl': 'io.ebean:ebean-ddl-generator:' + ebeanVersion, 'elasticSearchRest': 'org.elasticsearch.client:elasticsearch-rest-high-level-client:' + elasticsearchVersion, 'elasticSearchTransport': 'org.elasticsearch.client:transport:' + elasticsearchVersion, 'findbugsAnnotations': 'com.google.code.findbugs:annotations:3.0.1', @@ -96,7 +97,7 @@ project.ext.externalDependency = [ 'graphqlJavaScalars': 'com.graphql-java:graphql-java-extended-scalars:19.1', 'gson': 'com.google.code.gson:gson:2.8.9', 'guice': 'com.google.inject:guice:4.2.3', - 'guava': 'com.google.guava:guava:27.0.1-jre', + 'guava': 'com.google.guava:guava:32.1.2-jre', 'h2': 'com.h2database:h2:2.1.214', 'hadoopCommon':'org.apache.hadoop:hadoop-common:2.7.2', 'hadoopMapreduceClient':'org.apache.hadoop:hadoop-mapreduce-client-core:2.7.2', @@ -145,7 +146,7 @@ project.ext.externalDependency = [ 'log4jApi': "org.apache.logging.log4j:log4j-api:$log4jVersion", 'log4j12Api': "org.slf4j:log4j-over-slf4j:$slf4jVersion", 'log4j2Api': "org.apache.logging.log4j:log4j-to-slf4j:$log4jVersion", - 'lombok': 'org.projectlombok:lombok:1.18.12', + 'lombok': 'org.projectlombok:lombok:1.18.16', 'mariadbConnector': 'org.mariadb.jdbc:mariadb-java-client:2.6.0', 'mavenArtifact': "org.apache.maven:maven-artifact:$mavenVersion", 'mixpanel': 'com.mixpanel:mixpanel-java:1.4.4', @@ -186,7 +187,7 @@ project.ext.externalDependency = [ 'springBeans': "org.springframework:spring-beans:$springVersion", 'springContext': "org.springframework:spring-context:$springVersion", 'springCore': "org.springframework:spring-core:$springVersion", - 'springDocUI': 'org.springdoc:springdoc-openapi-ui:1.6.7', + 'springDocUI': 'org.springdoc:springdoc-openapi-ui:1.6.14', 'springJdbc': "org.springframework:spring-jdbc:$springVersion", 'springWeb': "org.springframework:spring-web:$springVersion", 'springWebMVC': "org.springframework:spring-webmvc:$springVersion", @@ -196,9 +197,11 @@ project.ext.externalDependency = [ 'springBootStarterWeb': "org.springframework.boot:spring-boot-starter-web:$springBootVersion", 'springBootStarterJetty': "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion", 'springBootStarterCache': "org.springframework.boot:spring-boot-starter-cache:$springBootVersion", + 'springBootStarterValidation': "org.springframework.boot:spring-boot-starter-validation:$springBootVersion", 'springKafka': 'org.springframework.kafka:spring-kafka:2.8.11', 'springActuator': "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion", 'swaggerAnnotations': 'io.swagger.core.v3:swagger-annotations:2.1.12', + 'swaggerCli': 'io.swagger.codegen.v3:swagger-codegen-cli:3.0.41', 'testng': 'org.testng:testng:7.3.0', 'testContainers': 'org.testcontainers:testcontainers:' + testContainersVersion, 'testContainersJunit': 'org.testcontainers:junit-jupiter:' + testContainersVersion, @@ -240,7 +243,7 @@ configure(subprojects.findAll {! it.name.startsWith('spark-lineage')}) { subprojects { - apply plugin: 'maven' + apply plugin: 'maven-publish' apply plugin: 'com.gorylenko.gradle-git-properties' gitProperties { @@ -254,7 +257,7 @@ subprojects { plugins.withType(JavaPlugin) { dependencies { - testCompile externalDependency.testng + testImplementation externalDependency.testng constraints { implementation('io.netty:netty-all:4.1.86.Final') implementation('org.apache.commons:commons-compress:1.21') diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 981a0ab2212172..65b3780431db9d 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -5,12 +5,15 @@ buildscript { } dependencies { - compile('io.acryl:json-schema-avro:0.1.5') { + implementation('io.acryl:json-schema-avro:0.1.5') { exclude group: 'com.fasterxml.jackson.core', module: 'jackson-databind' exclude group: 'com.google.guava', module: 'guava' } - compile 'com.google.guava:guava:27.0.1-jre' - compile 'com.fasterxml.jackson.core:jackson-databind:2.13.5' - compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.5' - compile 'commons-io:commons-io:2.11.0' + implementation 'com.google.guava:guava:32.1.2-jre' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.5' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.5' + implementation 'commons-io:commons-io:2.11.0' + + compileOnly 'org.projectlombok:lombok:1.18.14' + annotationProcessor 'org.projectlombok:lombok:1.18.14' } \ No newline at end of file diff --git a/buildSrc/src/main/java/com/linkedin/metadata/models/registry/config b/buildSrc/src/main/java/com/linkedin/metadata/models/registry/config new file mode 120000 index 00000000000000..ea22cc67da2d4b --- /dev/null +++ b/buildSrc/src/main/java/com/linkedin/metadata/models/registry/config @@ -0,0 +1 @@ +../../../../../../../../../entity-registry/src/main/java/com/linkedin/metadata/models/registry/config \ No newline at end of file diff --git a/buildSrc/src/main/java/io/datahubproject/GenerateJsonSchemaTask.java b/buildSrc/src/main/java/io/datahubproject/GenerateJsonSchemaTask.java index a5a843d91b1eb7..25bf239ab835b7 100644 --- a/buildSrc/src/main/java/io/datahubproject/GenerateJsonSchemaTask.java +++ b/buildSrc/src/main/java/io/datahubproject/GenerateJsonSchemaTask.java @@ -20,11 +20,9 @@ import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; + import org.gradle.api.DefaultTask; -import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.InputDirectory; -import org.gradle.api.tasks.OutputDirectory; -import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.*; import static com.github.fge.processing.ProcessingUtil.*; import static org.apache.commons.io.FilenameUtils.*; @@ -34,18 +32,33 @@ public class GenerateJsonSchemaTask extends DefaultTask { private String inputDirectory; private String outputDirectory; + private ArrayNode aspectType; private Path combinedDirectory; + private Path jsonDirectory; public static final String sep = FileSystems.getDefault().getSeparator(); private static final JsonNodeFactory NODE_FACTORY = JacksonUtils.nodeFactory(); + private static final OpenApiEntities openApiEntities = new OpenApiEntities(NODE_FACTORY); + + @InputFile + @PathSensitive(PathSensitivity.NAME_ONLY) + public String getEntityRegistryYaml() { + return openApiEntities.getEntityRegistryYaml(); + } + + public void setEntityRegistryYaml(String entityRegistryYaml) { + openApiEntities.setEntityRegistryYaml(entityRegistryYaml); + } + public void setInputDirectory(String inputDirectory) { this.inputDirectory = inputDirectory; } @InputDirectory + @PathSensitive(PathSensitivity.NAME_ONLY) public String getInputDirectory() { return inputDirectory; } @@ -80,6 +93,7 @@ public void generate() throws IOException { .filter(Files::isRegularFile) .map(Path::toFile) .forEach(this::generateSchema); + List nodesList = Files.walk(jsonDirectory) .filter(Files::isRegularFile) .filter(path -> { @@ -110,6 +124,18 @@ public void generate() throws IOException { } schemasNode.setAll(definitions); }); + + combinedDirectory = Paths.get(outputDirectory + sep + "combined"); + try { + Files.createDirectory(combinedDirectory); + } catch (FileAlreadyExistsException fae) { + // No-op + } + + // Add additional components and paths + openApiEntities.setCombinedDirectory(combinedDirectory); + ObjectNode extendedNode = openApiEntities.entityExtension(nodesList, schemasNode); + /* Minimal OpenAPI header openapi: 3.0.1 @@ -133,29 +159,23 @@ public void generate() throws IOException { .set("paths", NODE_FACTORY.objectNode() .set("/path", NODE_FACTORY.objectNode() .set("get", NODE_FACTORY.objectNode().set("tags", NODE_FACTORY.arrayNode().add("path"))))); - JsonNode combinedSchemaDefinitionsYaml = ((ObjectNode) NODE_FACTORY.objectNode().set("components", - NODE_FACTORY.objectNode().set("schemas", schemasNode))).setAll(yamlHeader); + + JsonNode combinedSchemaDefinitionsYaml = extendedNode.setAll(yamlHeader); final String yaml = new YAMLMapper().writeValueAsString(combinedSchemaDefinitionsYaml) - .replaceAll("definitions", "components/schemas") - .replaceAll("\n\\s+- type: \"null\"", ""); + .replaceAll("definitions", "components/schemas") + .replaceAll("\n\\s+description: null", "") + .replaceAll("\n\\s+- type: \"null\"", ""); - combinedDirectory = Paths.get(outputDirectory + sep + "combined"); - try { - Files.createDirectory(combinedDirectory); - } catch (FileAlreadyExistsException fae) { - // No-op - } Files.write(Paths.get(combinedDirectory + sep + "open-api.yaml"), yaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); - JsonNode combinedSchemaDefinitionsJson = NODE_FACTORY.objectNode().set("definitions",schemasNode); + JsonNode combinedSchemaDefinitionsJson = NODE_FACTORY.objectNode().set("definitions", extendedNode); String prettySchema = JacksonUtils.prettyPrint(combinedSchemaDefinitionsJson); Files.write(Paths.get(Paths.get(outputDirectory) + sep + "combined" + sep + "schema.json"), prettySchema.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); - } private final HashSet filenames = new HashSet<>(); @@ -185,5 +205,4 @@ private void generateSchema(final File file) { throw new RuntimeException(e); } } - } \ No newline at end of file diff --git a/buildSrc/src/main/java/io/datahubproject/OpenApiEntities.java b/buildSrc/src/main/java/io/datahubproject/OpenApiEntities.java new file mode 100644 index 00000000000000..7fbf013384b7db --- /dev/null +++ b/buildSrc/src/main/java/io/datahubproject/OpenApiEntities.java @@ -0,0 +1,603 @@ +package io.datahubproject; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import com.linkedin.metadata.models.registry.config.Entities; +import com.linkedin.metadata.models.registry.config.Entity; +import org.gradle.internal.Pair; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class OpenApiEntities { + private final static String MODEL_VERSION = "_v2"; + private final static String REQUEST_SUFFIX = "Request" + MODEL_VERSION; + private final static String RESPONSE_SUFFIX = "Response" + MODEL_VERSION; + + private final static String ASPECT_REQUEST_SUFFIX = "Aspect" + REQUEST_SUFFIX; + private final static String ASPECT_RESPONSE_SUFFIX = "Aspect" + RESPONSE_SUFFIX; + private final static String ENTITY_REQUEST_SUFFIX = "Entity" + REQUEST_SUFFIX; + private final static String ENTITY_RESPONSE_SUFFIX = "Entity" + RESPONSE_SUFFIX; + + private final JsonNodeFactory NODE_FACTORY; + private Map entityMap; + private String entityRegistryYaml; + private Path combinedDirectory; + + private final static Set SUPPORTED_ASPECT_PATHS = Set.of( + "domains", "ownership", "deprecation", "status", "globalTags", "glossaryTerms", "dataContractInfo", + "browsePathsV2" + ); + + public OpenApiEntities(JsonNodeFactory NODE_FACTORY) { + this.NODE_FACTORY = NODE_FACTORY; + } + + public String getEntityRegistryYaml() { + return entityRegistryYaml; + } + + public void setEntityRegistryYaml(String entityRegistryYaml) { + this.entityRegistryYaml = entityRegistryYaml; + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + mapper.findAndRegisterModules(); + try { + Entities entities = mapper.readValue(Paths.get(entityRegistryYaml).toFile(), Entities.class); + entityMap = entities.getEntities().stream() + .filter(e -> "core".equals(e.getCategory())) + .collect(Collectors.toMap(Entity::getName, Function.identity())); + } catch (IOException e) { + throw new IllegalArgumentException( + String.format("Error while reading entity yaml file in path %s: %s", entityRegistryYaml, e.getMessage())); + } + } + + public Path getCombinedDirectory() { + return combinedDirectory; + } + + public void setCombinedDirectory(Path combinedDirectory) { + this.combinedDirectory = combinedDirectory; + } + + public ObjectNode entityExtension(List nodesList, ObjectNode schemasNode) throws IOException { + // Generate entities schema + Set aspectDefinitions = nodesList.stream() + .map(nl -> nl.get("definitions").fieldNames()) + .flatMap(it -> StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false)) + .collect(Collectors.toSet()); + withWrappedAspects(schemasNode, aspectDefinitions); + + // Add entity schema + Set entitySchema = withEntitySchema(schemasNode, aspectDefinitions); + + // Write specific sections: components.* and paths + Set modelDefinitions = Stream.concat(aspectDefinitions.stream(), entitySchema.stream()) + .collect(Collectors.toSet()); + + // Just the component & parameters schema + Pair> parameters = buildParameters(schemasNode, modelDefinitions); + ObjectNode componentsNode = writeComponentsYaml(schemasNode, parameters.left()); + + // Just the entity paths + writePathsYaml(modelDefinitions, parameters.right()); + + return componentsNode; + } + + private static String toUpperFirst(String s) { + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + + private Set withEntitySchema(ObjectNode schemasNode, Set definitions) { + return entityMap.values().stream() + // Make sure the primary key is defined + .filter(entity -> definitions.contains(toUpperFirst(entity.getKeyAspect()))) + .map(entity -> { + final String upperName = toUpperFirst(entity.getName()); + + ObjectNode entityDefinitions = NODE_FACTORY.objectNode(); + entityDefinitions.set(upperName + ENTITY_RESPONSE_SUFFIX, buildEntitySchema(entity, definitions, true)); + entityDefinitions.set(upperName + ENTITY_REQUEST_SUFFIX, buildEntitySchema(entity, definitions, false)); + entityDefinitions.set("Scroll" + upperName + ENTITY_RESPONSE_SUFFIX, buildEntityScrollSchema(entity)); + + schemasNode.setAll(entityDefinitions); + + return upperName; + }).collect(Collectors.toSet()); + } + + + private Set withWrappedAspects(ObjectNode schemasNode, Set aspects) { + return aspects.stream().peek(aspect -> { + ObjectNode aspectRef = NODE_FACTORY.objectNode() + .put("$ref", "#/definitions/" + aspect); + + ObjectNode responseProperties = NODE_FACTORY.objectNode(); + responseProperties.set("value", aspectRef); + responseProperties.set("systemMetadata", NODE_FACTORY.objectNode() + .put("description", "System metadata for the aspect.") + .put("$ref", "#/definitions/SystemMetadata")); + + ObjectNode responseWrapper = NODE_FACTORY.objectNode() + .put("type", "object") + .put("description", "Aspect wrapper object.") + .set("properties", responseProperties); + responseWrapper.set("required", NODE_FACTORY.arrayNode().add("value")); + schemasNode.set(aspect + ASPECT_RESPONSE_SUFFIX, responseWrapper); + + ObjectNode requestProperties = NODE_FACTORY.objectNode(); + requestProperties.set("value", aspectRef); + + ObjectNode requestWrapper = NODE_FACTORY.objectNode() + .put("type", "object") + .put("description", "Aspect wrapper object.") + .set("properties", requestProperties); + requestWrapper.set("required", NODE_FACTORY.arrayNode().add("value")); + schemasNode.set(aspect + ASPECT_REQUEST_SUFFIX, requestWrapper); + }).collect(Collectors.toSet()); + } + + private ObjectNode buildEntitySchema(Entity entity, Set aspectDefinitions, boolean isResponse) { + ObjectNode propertiesNode = NODE_FACTORY.objectNode(); + + propertiesNode.set("urn", NODE_FACTORY.objectNode() + .put("description", "Unique id for " + entity.getName()) + .put("type", "string")); + + propertiesNode.set(entity.getKeyAspect(), buildAspectRef(entity.getKeyAspect(), isResponse)); + + entity.getAspects().stream() + .filter(aspect -> aspectDefinitions.contains(toUpperFirst(aspect))) // Only if aspect is defined + .forEach(aspect -> propertiesNode.set(aspect, buildAspectRef(aspect, isResponse))); + + ObjectNode entityNode = NODE_FACTORY.objectNode() + .put("type", "object") + .put("description", Optional.ofNullable(entity.getDoc()) + .orElse(toUpperFirst(entity.getName()) + " object.")) + .set("properties", propertiesNode); + entityNode.set("required", NODE_FACTORY.arrayNode().add("urn")); + + return entityNode; + } + + private ObjectNode buildEntityScrollSchema(Entity entity) { + ObjectNode scrollResponsePropertiesNode = NODE_FACTORY.objectNode(); + + scrollResponsePropertiesNode.set("scrollId", NODE_FACTORY.objectNode() + .put("description", "Scroll id for pagination.") + .put("type", "string")); + + scrollResponsePropertiesNode.set("entities", NODE_FACTORY.objectNode() + .put("description", Optional.ofNullable(entity.getDoc()) + .orElse(toUpperFirst(entity.getName()) + " object.")) + .put("type", "array") + .set("items", NODE_FACTORY.objectNode().put("$ref", + String.format("#/components/schemas/%s%s", toUpperFirst(entity.getName()), ENTITY_RESPONSE_SUFFIX)))); + + ObjectNode scrollResponseNode = NODE_FACTORY.objectNode() + .put("type", "object") + .put("description", "Scroll across " + toUpperFirst(entity.getName()) + " objects.") + .set("properties", scrollResponsePropertiesNode); + scrollResponseNode.set("required", NODE_FACTORY.arrayNode().add("entities")); + + return scrollResponseNode; + } + + + private ObjectNode buildAspectRef(String aspect, boolean withSystemMetadata) { + if (withSystemMetadata) { + return NODE_FACTORY.objectNode() + .put("$ref", String.format("#/definitions/%s%s", toUpperFirst(aspect), ASPECT_RESPONSE_SUFFIX)); + } else { + return NODE_FACTORY.objectNode() + .put("$ref", String.format("#/definitions/%s%s", toUpperFirst(aspect), ASPECT_REQUEST_SUFFIX)); + } + } + + private Optional> generateEntityParameters(final Entity entity, Set definitions) { + /* + If not missing key + */ + if (definitions.contains(toUpperFirst(entity.getKeyAspect()))) { + final String parameterName = toUpperFirst(entity.getName()) + "Aspects"; + + ArrayNode aspects = NODE_FACTORY.arrayNode(); + entity.getAspects().stream() + .filter(aspect -> definitions.contains(toUpperFirst(aspect))) // Only if aspect is defined + .distinct() + .forEach(aspects::add); + + if (aspects.isEmpty()) { + aspects.add(entity.getKeyAspect()); + } + + ObjectNode itemsNode = NODE_FACTORY.objectNode() + .put("type", "string"); + itemsNode.set("enum", aspects); + itemsNode.set("default", aspects); + + ObjectNode schemaNode = NODE_FACTORY.objectNode() + .put("type", "array") + .set("items", itemsNode); + ObjectNode parameterSchemaNode = NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "aspects") + .put("explode", true) + .put("description", "Aspects to include in response.") + .set("schema", schemaNode); + + parameterSchemaNode.set("example", aspects); + + ObjectNode parameterNode = NODE_FACTORY.objectNode() + .set(parameterName + MODEL_VERSION, parameterSchemaNode); + + return Optional.of(Pair.of(parameterName, parameterNode)); + } + + return Optional.empty(); + } + + private Pair> buildParameters(ObjectNode schemasNode, Set definitions) { + ObjectNode parametersNode = NODE_FACTORY.objectNode(); + Set parameterDefinitions = entityMap.values().stream() + .flatMap(entity -> generateEntityParameters(entity, definitions).stream()) + .map(entityNode -> { + parametersNode.setAll(entityNode.right()); + return entityNode.left(); + }) + .collect(Collectors.toSet()); + + return Pair.of(extraParameters(parametersNode), parameterDefinitions); + } + + private ObjectNode writeComponentsYaml(ObjectNode schemasNode, ObjectNode parametersNode) throws IOException { + ObjectNode componentsNode = NODE_FACTORY.objectNode(); + componentsNode.set("schemas", schemasNode); + componentsNode.set("parameters", extraParameters(parametersNode)); + ObjectNode componentsDocNode = NODE_FACTORY.objectNode().set("components", componentsNode); + + final String componentsYaml = new YAMLMapper().writeValueAsString(componentsDocNode) + .replaceAll("definitions", "components/schemas") + .replaceAll("\n\\s+description: null", "") + .replaceAll("\n\\s+- type: \"null\"", ""); + Files.write(Paths.get(combinedDirectory + GenerateJsonSchemaTask.sep + "open-api-components.yaml"), + componentsYaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + + return componentsDocNode; + } + + private ObjectNode extraParameters(ObjectNode parametersNode) { + parametersNode.set("ScrollId" + MODEL_VERSION, NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "scrollId") + .put("description", "Scroll pagination token.") + .set("schema", NODE_FACTORY.objectNode() + .put("type", "string"))); + + ArrayNode sortFields = NODE_FACTORY.arrayNode(); + sortFields.add("urn"); + ObjectNode sortFieldsNode = NODE_FACTORY.objectNode() + .put("type", "string"); + sortFieldsNode.set("enum", sortFields); + sortFieldsNode.set("default", sortFields.get(0)); + + ObjectNode sortFieldsSchemaNode = NODE_FACTORY.objectNode() + .put("type", "array") + .put("default", "urn") + .set("items", sortFieldsNode); + parametersNode.set("SortBy" + MODEL_VERSION, NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "sort") + .put("explode", true) + .put("description", "Sort fields for pagination.") + .put("example", "urn") + .set("schema", sortFieldsSchemaNode)); + + parametersNode.set("SortOrder" + MODEL_VERSION, NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "sortOrder") + .put("explode", true) + .put("description", "Sort direction field for pagination.") + .put("example", "ASCENDING") + .set("schema", NODE_FACTORY.objectNode() + .put("default", "ASCENDING") + .put("$ref", "#/components/schemas/SortOrder"))); + + parametersNode.set("PaginationCount" + MODEL_VERSION, NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "count") + .put("description", "Number of items per page.") + .put("example", "10") + .set("schema", NODE_FACTORY.objectNode() + .put("type", "integer") + .put("default", 10) + .put("minimum", 1))); + parametersNode.set("ScrollQuery" + MODEL_VERSION, NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "query") + .put("description", "Structured search query.") + .put("example", "*") + .set("schema", NODE_FACTORY.objectNode() + .put("type", "string") + .put("default", "*"))); + + return parametersNode; + } + + private void writePathsYaml(Set modelDefinitions, Set parameterDefinitions) throws IOException { + ObjectNode pathsNode = NODE_FACTORY.objectNode(); + + entityMap.values().stream() + .filter(e -> modelDefinitions.contains(toUpperFirst(e.getName()))) + .forEach(entity -> { + + pathsNode.set(String.format("/%s", entity.getName().toLowerCase()), + buildListEntityPath(entity, parameterDefinitions)); + + pathsNode.set(String.format("/%s/{urn}", entity.getName().toLowerCase()), + buildSingleEntityPath(entity, parameterDefinitions)); + + }); + + buildEntityAspectPaths(pathsNode, modelDefinitions); + + ObjectNode pathsDocNode = NODE_FACTORY.objectNode().set("paths", pathsNode); + + final String componentsYaml = new YAMLMapper().writeValueAsString(pathsDocNode) + .replaceAll("\n\\s+- type: \"null\"", "") + .replaceAll("\n\\s+description: null", ""); + Files.write(Paths.get(combinedDirectory + GenerateJsonSchemaTask.sep + "open-api-paths.yaml"), + componentsYaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + } + + private void buildEntityAspectPaths(ObjectNode pathsNode, Set modelDefinitions) { + entityMap.values().stream() + .filter(e -> modelDefinitions.contains(toUpperFirst(e.getName()))) + .forEach(entity -> { + entity.getAspects().stream() + .filter(aspect -> SUPPORTED_ASPECT_PATHS.contains(aspect)) + .filter(aspect -> modelDefinitions.contains(toUpperFirst(aspect))) + .forEach(aspect -> pathsNode.set(String.format("/%s/{urn}/%s", + entity.getName().toLowerCase(), aspect.toLowerCase()), + buildSingleEntityAspectPath(entity, aspect))); + }); + } + + private ObjectNode buildListEntityPath(Entity entity, Set parameterDefinitions) { + final String upperFirst = toUpperFirst(entity.getName()); + final String aspectParameterName = upperFirst + "Aspects"; + ArrayNode tagsNode = NODE_FACTORY.arrayNode() + .add(entity.getName() + " Entity"); + + ObjectNode scrollMethod = NODE_FACTORY.objectNode() + .put("summary", String.format("Scroll %s.", upperFirst)) + .put("operationId", String.format("scroll", upperFirst)); + + ArrayNode scrollPathParametersNode = NODE_FACTORY.arrayNode(); + scrollMethod.set("parameters", scrollPathParametersNode); + scrollPathParametersNode.add(NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "systemMetadata") + .put("description", "Include systemMetadata with response.") + .set("schema", NODE_FACTORY.objectNode() + .put("type", "boolean") + .put("default", false))); + if (parameterDefinitions.contains(aspectParameterName)) { + scrollPathParametersNode.add(NODE_FACTORY.objectNode() + .put("$ref", String.format("#/components/parameters/%s", aspectParameterName + MODEL_VERSION))); + } + scrollPathParametersNode.add(NODE_FACTORY.objectNode() + .put("$ref", "#/components/parameters/PaginationCount" + MODEL_VERSION)); + scrollPathParametersNode.add(NODE_FACTORY.objectNode() + .put("$ref", "#/components/parameters/ScrollId" + MODEL_VERSION)); + scrollPathParametersNode.add(NODE_FACTORY.objectNode() + .put("$ref", "#/components/parameters/SortBy" + MODEL_VERSION)); + scrollPathParametersNode.add(NODE_FACTORY.objectNode() + .put("$ref", "#/components/parameters/SortOrder" + MODEL_VERSION)); + scrollPathParametersNode.add(NODE_FACTORY.objectNode() + .put("$ref", "#/components/parameters/ScrollQuery" + MODEL_VERSION)); + scrollMethod.set("parameters", scrollPathParametersNode); + scrollMethod.set("responses", NODE_FACTORY.objectNode() + .set("200", NODE_FACTORY.objectNode().put("description", "Success") + .set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode() + .set("schema", NODE_FACTORY.objectNode() + .put("$ref", String.format("#/components/schemas/Scroll%s%s", upperFirst, ENTITY_RESPONSE_SUFFIX))))))); + scrollMethod.set("tags", tagsNode); + + ObjectNode postMethod = NODE_FACTORY.objectNode() + .put("summary", "Create " + upperFirst) + .put("operationId", String.format("create", upperFirst)); + postMethod.set("requestBody", NODE_FACTORY.objectNode() + .put("description", "Create " + entity.getName() + " entities.") + .put("required", true) + .set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode() + .set("schema", NODE_FACTORY.objectNode().put("type", "array") + .set("items", NODE_FACTORY.objectNode().put("$ref", + String.format("#/components/schemas/%s%s", upperFirst, ENTITY_REQUEST_SUFFIX))))))); + postMethod.set("responses", NODE_FACTORY.objectNode() + .set("201", NODE_FACTORY.objectNode().put("description", "Create " + entity.getName() + " entities.") + .set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode() + .set("schema", NODE_FACTORY.objectNode().put("type", "array") + .set("items", NODE_FACTORY.objectNode().put("$ref", + String.format("#/components/schemas/%s%s", upperFirst, ENTITY_RESPONSE_SUFFIX)))))))); + postMethod.set("tags", tagsNode); + + ObjectNode listMethods = NODE_FACTORY.objectNode(); + listMethods.set("get", scrollMethod); + listMethods.set("post", postMethod); + + return listMethods; + } + + private ObjectNode buildSingleEntityPath(Entity entity, Set parameterDefinitions) { + final String upperFirst = toUpperFirst(entity.getName()); + final String aspectParameterName = upperFirst + "Aspects"; + ArrayNode tagsNode = NODE_FACTORY.arrayNode().add(entity.getName() + " Entity"); + + ObjectNode getMethod = NODE_FACTORY.objectNode() + .put("summary", String.format("Get %s by key.", entity.getName())) + .put("operationId", String.format("get", upperFirst)); + getMethod.set("tags", tagsNode); + ArrayNode singlePathParametersNode = NODE_FACTORY.arrayNode(); + getMethod.set("parameters", singlePathParametersNode); + singlePathParametersNode.add(NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "systemMetadata") + .put("description", "Include systemMetadata with response.") + .set("schema", NODE_FACTORY.objectNode() + .put("type", "boolean") + .put("default", false))); + if(parameterDefinitions.contains(aspectParameterName)) { + singlePathParametersNode.add(NODE_FACTORY.objectNode() + .put("$ref", String.format("#/components/parameters/%s", aspectParameterName + MODEL_VERSION))); + } + + ObjectNode responses = NODE_FACTORY.objectNode(); + getMethod.set("responses", responses); + responses.set("200", NODE_FACTORY.objectNode().put("description", "Success") + .set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode() + .set("schema", NODE_FACTORY.objectNode().put("$ref", + String.format("#/components/schemas/%s%s", upperFirst, ENTITY_RESPONSE_SUFFIX)))))); + responses.set("404", NODE_FACTORY.objectNode() + .put("description", "Not Found") + .set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode() + .set("schema", NODE_FACTORY.objectNode())))); + + ObjectNode headResponses = NODE_FACTORY.objectNode(); + headResponses.set("204", NODE_FACTORY.objectNode() + .put("description", entity.getName() + " exists.") + .set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode()))); + headResponses.set("404", NODE_FACTORY.objectNode() + .put("description", entity.getName() + " does not exist.") + .set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode()))); + ObjectNode headMethod = NODE_FACTORY.objectNode() + .put("summary", upperFirst + " existence.") + .put("operationId", String.format("head", upperFirst)) + .set("responses", headResponses); + headMethod.set("tags", tagsNode); + + ObjectNode deleteMethod = NODE_FACTORY.objectNode() + .put("summary", "Delete entity " + upperFirst) + .put("operationId", String.format("delete", upperFirst)) + .set("responses", NODE_FACTORY.objectNode() + .set("200", NODE_FACTORY.objectNode() + .put("description", "Delete " + entity.getName() + " entity.") + .set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode())))); + deleteMethod.set("tags", tagsNode); + + ObjectNode singlePathMethods = NODE_FACTORY.objectNode() + .set("parameters", NODE_FACTORY.arrayNode() + .add(NODE_FACTORY.objectNode() + .put("in", "path") + .put("name", "urn") + .put("required", true) + .set("schema", NODE_FACTORY.objectNode().put("type", "string")))); + singlePathMethods.set("get", getMethod); + singlePathMethods.set("head", headMethod); + singlePathMethods.set("delete", deleteMethod); + + return singlePathMethods; + } + + private ObjectNode buildSingleEntityAspectPath(Entity entity, String aspect) { + final String upperFirstEntity = toUpperFirst(entity.getName()); + final String upperFirstAspect = toUpperFirst(aspect); + + ArrayNode tagsNode = NODE_FACTORY.arrayNode() + .add(aspect + " Aspect"); + + ObjectNode getMethod = NODE_FACTORY.objectNode() + .put("summary", String.format("Get %s for %s.", aspect, entity.getName())) + .put("operationId", String.format("get%s", upperFirstAspect, upperFirstEntity)); + getMethod.set("tags", tagsNode); + ArrayNode singlePathParametersNode = NODE_FACTORY.arrayNode(); + getMethod.set("parameters", singlePathParametersNode); + singlePathParametersNode.add(NODE_FACTORY.objectNode() + .put("in", "query") + .put("name", "systemMetadata") + .put("description", "Include systemMetadata with response.") + .set("schema", NODE_FACTORY.objectNode() + .put("type", "boolean") + .put("default", false))); + getMethod.set("responses", NODE_FACTORY.objectNode().set("200", NODE_FACTORY.objectNode() + .put("description", "Success").set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode().set("schema", NODE_FACTORY.objectNode() + .put("$ref", + String.format("#/components/schemas/%s%s", upperFirstAspect, ASPECT_RESPONSE_SUFFIX))))))); + + ObjectNode headResponses = NODE_FACTORY.objectNode(); + headResponses.set("200", NODE_FACTORY.objectNode() + .put("description", String.format("%s on %s exists.", aspect, entity.getName())) + .set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode()))); + headResponses.set("404", NODE_FACTORY.objectNode() + .put("description", String.format("%s on %s does not exist.", aspect, entity.getName())) + .set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode()))); + ObjectNode headMethod = NODE_FACTORY.objectNode() + .put("summary", String.format("%s on %s existence.", aspect, upperFirstEntity)) + .put("operationId", String.format("head%s", upperFirstAspect, upperFirstEntity)) + .set("responses", headResponses); + headMethod.set("tags", tagsNode); + + ObjectNode deleteMethod = NODE_FACTORY.objectNode() + .put("summary", String.format("Delete %s on entity %s", aspect, upperFirstEntity)) + .put("operationId", String.format("delete%s", upperFirstAspect, upperFirstEntity)) + .set("responses", NODE_FACTORY.objectNode() + .set("200", NODE_FACTORY.objectNode() + .put("description", String.format("Delete %s on %s entity.", aspect, upperFirstEntity)) + .set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode())))); + deleteMethod.set("tags", tagsNode); + + ObjectNode postMethod = NODE_FACTORY.objectNode() + .put("summary", String.format("Create aspect %s on %s ", aspect, upperFirstEntity)) + .put("operationId", String.format("create%s", upperFirstAspect, upperFirstEntity)); + postMethod.set("requestBody", NODE_FACTORY.objectNode() + .put("description", String.format("Create aspect %s on %s entity.", aspect, upperFirstEntity)) + .put("required", true).set("content", NODE_FACTORY.objectNode() + .set("application/json", NODE_FACTORY.objectNode().set("schema", NODE_FACTORY.objectNode() + .put("$ref", + String.format("#/components/schemas/%s%s", upperFirstAspect, ASPECT_REQUEST_SUFFIX)))))); + postMethod.set("responses", NODE_FACTORY.objectNode().set("201", NODE_FACTORY.objectNode() + .put("description", String.format("Create aspect %s on %s entity.", aspect, upperFirstEntity)) + .set("content", NODE_FACTORY.objectNode().set("application/json", NODE_FACTORY.objectNode() + .set("schema", NODE_FACTORY.objectNode().put("$ref", + String.format("#/components/schemas/%s%s", upperFirstAspect, ASPECT_RESPONSE_SUFFIX))))))); + postMethod.set("tags", tagsNode); + + ObjectNode singlePathMethods = NODE_FACTORY.objectNode() + .set("parameters", NODE_FACTORY.arrayNode() + .add(NODE_FACTORY.objectNode() + .put("in", "path") + .put("name", "urn") + .put("required", true) + .set("schema", NODE_FACTORY.objectNode().put("type", "string")))); + singlePathMethods.set("get", getMethod); + singlePathMethods.set("head", headMethod); + singlePathMethods.set("delete", deleteMethod); + singlePathMethods.set("post", postMethod); + + return singlePathMethods; + } +} diff --git a/datahub-frontend/app/controllers/CentralLogoutController.java b/datahub-frontend/app/controllers/CentralLogoutController.java index b1220c7f3f111b..5e24fe9f8220cf 100644 --- a/datahub-frontend/app/controllers/CentralLogoutController.java +++ b/datahub-frontend/app/controllers/CentralLogoutController.java @@ -16,7 +16,8 @@ */ @Slf4j public class CentralLogoutController extends LogoutController { - private static final String DEFAULT_BASE_URL_PATH = "/login"; + private static final String AUTH_URL_CONFIG_PATH = "/login"; + private static final String DEFAULT_BASE_URL_PATH = "/"; private static Boolean _isOidcEnabled = false; @Inject @@ -36,8 +37,7 @@ public CentralLogoutController(Config config) { public Result executeLogout(Http.Request request) { if (_isOidcEnabled) { try { - return Results.redirect(DEFAULT_BASE_URL_PATH) - .removingFromSession(request); + return logout(request).toCompletableFuture().get().withNewSession(); } catch (Exception e) { log.error("Caught exception while attempting to perform SSO logout! It's likely that SSO integration is mis-configured.", e); return redirect( @@ -47,7 +47,7 @@ public Result executeLogout(Http.Request request) { .withNewSession(); } } - return Results.redirect(DEFAULT_BASE_URL_PATH) + return Results.redirect(AUTH_URL_CONFIG_PATH) .withNewSession(); } } diff --git a/datahub-frontend/build.gradle b/datahub-frontend/build.gradle index fda33e4a9a3c63..fdf13bac0accc0 100644 --- a/datahub-frontend/build.gradle +++ b/datahub-frontend/build.gradle @@ -1,7 +1,7 @@ plugins { id "io.github.kobylynskyi.graphql.codegen" version "4.1.1" - id 'com.palantir.docker' id 'scala' + id 'com.palantir.docker' } apply from: "../gradle/versioning/versioning.gradle" @@ -96,7 +96,7 @@ task unversionZip(type: Copy, dependsOn: [':datahub-web-react:build', dist]) { into "${buildDir}/docker/" rename "datahub-frontend-${version}.zip", "datahub-frontend.zip" } -tasks.getByName("docker").dependsOn(unversionZip) +tasks.getByPath(":datahub-frontend:docker").dependsOn(unversionZip) task cleanLocalDockerImages { doLast { diff --git a/datahub-frontend/conf/application.conf b/datahub-frontend/conf/application.conf index 2a3d7f395736ef..18d901d5ee7ddc 100644 --- a/datahub-frontend/conf/application.conf +++ b/datahub-frontend/conf/application.conf @@ -200,7 +200,7 @@ auth.native.enabled = ${?AUTH_NATIVE_ENABLED} # auth.oidc.enabled = false # (or simply omit oidc configurations) # Login session expiration time -auth.session.ttlInHours = 720 +auth.session.ttlInHours = 24 auth.session.ttlInHours = ${?AUTH_SESSION_TTL_HOURS} analytics.enabled = true diff --git a/datahub-frontend/conf/routes b/datahub-frontend/conf/routes index 38e6f769027f08..3102c26497fedd 100644 --- a/datahub-frontend/conf/routes +++ b/datahub-frontend/conf/routes @@ -33,6 +33,8 @@ GET /openapi/*path c POST /openapi/*path controllers.Application.proxy(path: String, request: Request) DELETE /openapi/*path controllers.Application.proxy(path: String, request: Request) PUT /openapi/*path controllers.Application.proxy(path: String, request: Request) +HEAD /openapi/*path controllers.Application.proxy(path: String, request: Request) +PATCH /openapi/*path controllers.Application.proxy(path: String, request: Request) # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.at(path="/public", file) diff --git a/datahub-frontend/play.gradle b/datahub-frontend/play.gradle index e7121d277926de..e40f8e3eeb96de 100644 --- a/datahub-frontend/play.gradle +++ b/datahub-frontend/play.gradle @@ -4,7 +4,7 @@ apply plugin: "org.gradle.playframework" project.ext.httpPort = 9001 project.ext.playBinaryBaseName = "datahub-frontend" -tasks.withType(PlayRun) { +runPlay { httpPort = project.ext.httpPort } @@ -33,8 +33,8 @@ dependencies { } } - compile project(":metadata-service:restli-client") - compile project(":metadata-service:auth-config") + implementation project(":metadata-service:restli-client") + implementation project(":metadata-service:auth-config") implementation externalDependency.jettyJaas implementation externalDependency.graphqlJava @@ -70,15 +70,15 @@ dependencies { testImplementation 'no.nav.security:mock-oauth2-server:0.3.1' testImplementation 'org.junit-pioneer:junit-pioneer:1.9.1' testImplementation externalDependency.junitJupiterApi - testRuntime externalDependency.junitJupiterEngine + testRuntimeOnly externalDependency.junitJupiterEngine implementation externalDependency.slf4jApi compileOnly externalDependency.lombok - runtime externalDependency.guice - runtime (externalDependency.playDocs) { + runtimeOnly externalDependency.guice + runtimeOnly (externalDependency.playDocs) { exclude group: 'com.typesafe.akka', module: 'akka-http-core_2.12' } - runtime externalDependency.playGuice + runtimeOnly externalDependency.playGuice implementation externalDependency.log4j2Api implementation externalDependency.logbackClassic diff --git a/datahub-graphql-core/build.gradle b/datahub-graphql-core/build.gradle index 8fd45033373dc6..89ba8f17b6aebd 100644 --- a/datahub-graphql-core/build.gradle +++ b/datahub-graphql-core/build.gradle @@ -4,25 +4,26 @@ plugins { apply plugin: 'java' dependencies { - compile project(':metadata-service:restli-client') - compile project(':metadata-service:auth-impl') - compile project(':metadata-service:auth-config') - compile project(':metadata-service:configuration') - compile project(':metadata-service:services') - compile project(':metadata-io') - compile project(':metadata-utils') + implementation project(':metadata-service:restli-client') + implementation project(':metadata-service:auth-impl') + implementation project(':metadata-service:auth-config') + implementation project(':metadata-service:configuration') + implementation project(':metadata-service:services') + implementation project(':metadata-io') + implementation project(':metadata-utils') implementation externalDependency.graphqlJava implementation externalDependency.graphqlJavaScalars - compile externalDependency.antlr4Runtime - compile externalDependency.antlr4 - compile externalDependency.guava + implementation externalDependency.antlr4Runtime + implementation externalDependency.antlr4 + implementation externalDependency.guava + implementation externalDependency.opentelemetryAnnotations implementation externalDependency.slf4jApi compileOnly externalDependency.lombok annotationProcessor externalDependency.lombok - testCompile externalDependency.mockito + testImplementation externalDependency.mockito } graphqlCodegen { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java index d6dd2de6d31e35..d86234cf593062 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java @@ -68,6 +68,7 @@ import com.linkedin.datahub.graphql.generated.ListQueriesResult; import com.linkedin.datahub.graphql.generated.ListTestsResult; import com.linkedin.datahub.graphql.generated.ListViewsResult; +import com.linkedin.datahub.graphql.generated.MatchedField; import com.linkedin.datahub.graphql.generated.MLFeature; import com.linkedin.datahub.graphql.generated.MLFeatureProperties; import com.linkedin.datahub.graphql.generated.MLFeatureTable; @@ -80,6 +81,7 @@ import com.linkedin.datahub.graphql.generated.Notebook; import com.linkedin.datahub.graphql.generated.Owner; import com.linkedin.datahub.graphql.generated.OwnershipTypeEntity; +import com.linkedin.datahub.graphql.generated.ParentDomainsResult; import com.linkedin.datahub.graphql.generated.PolicyMatchCriterionValue; import com.linkedin.datahub.graphql.generated.QueryEntity; import com.linkedin.datahub.graphql.generated.QuerySubject; @@ -123,6 +125,7 @@ import com.linkedin.datahub.graphql.resolvers.domain.DeleteDomainResolver; import com.linkedin.datahub.graphql.resolvers.domain.DomainEntitiesResolver; import com.linkedin.datahub.graphql.resolvers.domain.ListDomainsResolver; +import com.linkedin.datahub.graphql.resolvers.domain.ParentDomainsResolver; import com.linkedin.datahub.graphql.resolvers.domain.SetDomainResolver; import com.linkedin.datahub.graphql.resolvers.domain.UnsetDomainResolver; import com.linkedin.datahub.graphql.resolvers.embed.UpdateEmbedResolver; @@ -185,6 +188,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.BatchSetDomainResolver; import com.linkedin.datahub.graphql.resolvers.mutate.BatchUpdateDeprecationResolver; import com.linkedin.datahub.graphql.resolvers.mutate.BatchUpdateSoftDeletedResolver; +import com.linkedin.datahub.graphql.resolvers.mutate.MoveDomainResolver; import com.linkedin.datahub.graphql.resolvers.mutate.MutableTypeBatchResolver; import com.linkedin.datahub.graphql.resolvers.mutate.MutableTypeResolver; import com.linkedin.datahub.graphql.resolvers.mutate.RemoveLinkResolver; @@ -943,6 +947,7 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) { .dataFetcher("removeGroup", new RemoveGroupResolver(this.entityClient)) .dataFetcher("updateUserStatus", new UpdateUserStatusResolver(this.entityClient)) .dataFetcher("createDomain", new CreateDomainResolver(this.entityClient, this.entityService)) + .dataFetcher("moveDomain", new MoveDomainResolver(this.entityService, this.entityClient)) .dataFetcher("deleteDomain", new DeleteDomainResolver(entityClient)) .dataFetcher("setDomain", new SetDomainResolver(this.entityClient, this.entityService)) .dataFetcher("batchSetDomain", new BatchSetDomainResolver(this.entityService)) @@ -1008,6 +1013,10 @@ private void configureGenericEntityResolvers(final RuntimeWiring.Builder builder .dataFetcher("entity", new EntityTypeResolver(entityTypes, (env) -> ((SearchResult) env.getSource()).getEntity())) ) + .type("MatchedField", typeWiring -> typeWiring + .dataFetcher("entity", new EntityTypeResolver(entityTypes, + (env) -> ((MatchedField) env.getSource()).getEntity())) + ) .type("SearchAcrossLineageResult", typeWiring -> typeWiring .dataFetcher("entity", new EntityTypeResolver(entityTypes, (env) -> ((SearchAcrossLineageResult) env.getSource()).getEntity())) @@ -1024,6 +1033,13 @@ private void configureGenericEntityResolvers(final RuntimeWiring.Builder builder .dataFetcher("entities", new EntityTypeBatchResolver(entityTypes, (env) -> ((BrowseResults) env.getSource()).getEntities())) ) + .type("ParentDomainsResult", typeWiring -> typeWiring + .dataFetcher("domains", new EntityTypeBatchResolver(entityTypes, + (env) -> { + final ParentDomainsResult result = env.getSource(); + return result != null ? result.getDomains() : null; + })) + ) .type("EntityRelationshipLegacy", typeWiring -> typeWiring .dataFetcher("entity", new EntityTypeResolver(entityTypes, (env) -> ((EntityRelationshipLegacy) env.getSource()).getEntity())) @@ -1670,8 +1686,8 @@ private void configureGlossaryRelationshipResolvers(final RuntimeWiring.Builder private void configureDomainResolvers(final RuntimeWiring.Builder builder) { builder.type("Domain", typeWiring -> typeWiring .dataFetcher("entities", new DomainEntitiesResolver(this.entityClient)) - .dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient) - ) + .dataFetcher("parentDomains", new ParentDomainsResolver(this.entityClient)) + .dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient)) ); builder.type("DomainAssociation", typeWiring -> typeWiring .dataFetcher("domain", diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/authorization/AuthorizationUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/authorization/AuthorizationUtils.java index 94880c77d74bcc..3089b8c8fc2dba 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/authorization/AuthorizationUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/authorization/AuthorizationUtils.java @@ -107,7 +107,31 @@ public static boolean canEditGroupMembers(@Nonnull String groupUrnStr, @Nonnull } public static boolean canCreateGlobalAnnouncements(@Nonnull QueryContext context) { - return isAuthorized(context, Optional.empty(), PoliciesConfig.CREATE_GLOBAL_ANNOUNCEMENTS_PRIVILEGE); + final DisjunctivePrivilegeGroup orPrivilegeGroups = new DisjunctivePrivilegeGroup( + ImmutableList.of( + new ConjunctivePrivilegeGroup(ImmutableList.of( + PoliciesConfig.CREATE_GLOBAL_ANNOUNCEMENTS_PRIVILEGE.getType())), + new ConjunctivePrivilegeGroup(ImmutableList.of( + PoliciesConfig.MANAGE_GLOBAL_ANNOUNCEMENTS_PRIVILEGE.getType())) + )); + + return AuthorizationUtils.isAuthorized( + context.getAuthorizer(), + context.getActorUrn(), + orPrivilegeGroups); + } + + public static boolean canManageGlobalAnnouncements(@Nonnull QueryContext context) { + final DisjunctivePrivilegeGroup orPrivilegeGroups = new DisjunctivePrivilegeGroup( + ImmutableList.of( + new ConjunctivePrivilegeGroup(ImmutableList.of( + PoliciesConfig.MANAGE_GLOBAL_ANNOUNCEMENTS_PRIVILEGE.getType())) + )); + + return AuthorizationUtils.isAuthorized( + context.getAuthorizer(), + context.getActorUrn(), + orPrivilegeGroups); } public static boolean canManageGlobalViews(@Nonnull QueryContext context) { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/exception/DataHubGraphQLErrorCode.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/exception/DataHubGraphQLErrorCode.java index db3e1dd03e4198..44695c334855fc 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/exception/DataHubGraphQLErrorCode.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/exception/DataHubGraphQLErrorCode.java @@ -4,6 +4,7 @@ public enum DataHubGraphQLErrorCode { BAD_REQUEST(400), UNAUTHORIZED(403), NOT_FOUND(404), + CONFLICT(409), SERVER_ERROR(500); private final int _code; diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/featureflags/FeatureFlags.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/featureflags/FeatureFlags.java index f8135629453786..4d6133f18df050 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/featureflags/FeatureFlags.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/featureflags/FeatureFlags.java @@ -15,4 +15,6 @@ public class FeatureFlags { private boolean showBrowseV2 = false; private PreProcessHooks preProcessHooks; private boolean showAcrylInfo = false; + private boolean showAccessManagement = false; + private boolean nestedDomainsEnabled = false; } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/MeResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/MeResolver.java index d2a7b19857f95f..02921b453e3154 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/MeResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/MeResolver.java @@ -74,6 +74,7 @@ public CompletableFuture get(DataFetchingEnvironment environm platformPrivileges.setManageTags(AuthorizationUtils.canManageTags(context)); platformPrivileges.setManageGlobalViews(AuthorizationUtils.canManageGlobalViews(context)); platformPrivileges.setManageOwnershipTypes(AuthorizationUtils.canManageOwnershipTypes(context)); + platformPrivileges.setManageGlobalAnnouncements(AuthorizationUtils.canManageGlobalAnnouncements(context)); // Construct and return authenticated user object. final AuthenticatedUser authUser = new AuthenticatedUser(); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java index 2c55bc79fe5017..f6bc68caa0821c 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java @@ -18,6 +18,7 @@ import com.linkedin.datahub.graphql.generated.Privilege; import com.linkedin.datahub.graphql.generated.QueriesTabConfig; import com.linkedin.datahub.graphql.generated.ResourcePrivileges; +import com.linkedin.datahub.graphql.generated.SearchResultsVisualConfig; import com.linkedin.datahub.graphql.generated.TelemetryConfig; import com.linkedin.datahub.graphql.generated.TestsConfig; import com.linkedin.datahub.graphql.generated.ViewsConfig; @@ -144,6 +145,13 @@ public CompletableFuture get(final DataFetchingEnvironment environmen } visualConfig.setEntityProfiles(entityProfilesConfig); } + if (_visualConfiguration != null && _visualConfiguration.getSearchResult() != null) { + SearchResultsVisualConfig searchResultsVisualConfig = new SearchResultsVisualConfig(); + if (_visualConfiguration.getSearchResult().getEnableNameHighlight() != null) { + searchResultsVisualConfig.setEnableNameHighlight(_visualConfiguration.getSearchResult().getEnableNameHighlight()); + } + visualConfig.setSearchResult(searchResultsVisualConfig); + } appConfig.setVisualConfig(visualConfig); final TelemetryConfig telemetryConfig = new TelemetryConfig(); @@ -163,6 +171,8 @@ public CompletableFuture get(final DataFetchingEnvironment environmen .setReadOnlyModeEnabled(_featureFlags.isReadOnlyModeEnabled()) .setShowBrowseV2(_featureFlags.isShowBrowseV2()) .setShowAcrylInfo(_featureFlags.isShowAcrylInfo()) + .setShowAccessManagement(_featureFlags.isShowAccessManagement()) + .setNestedDomainsEnabled(_featureFlags.isNestedDomainsEnabled()) .build(); appConfig.setFeatureFlags(featureFlagsConfig); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolver.java index 39aa1ea28da205..1930cdc1f86676 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolver.java @@ -1,14 +1,18 @@ package com.linkedin.datahub.graphql.resolvers.domain; import com.linkedin.common.AuditStamp; +import com.linkedin.common.urn.Urn; import com.linkedin.common.urn.UrnUtils; import com.linkedin.data.template.SetMode; import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; import com.linkedin.datahub.graphql.exception.AuthorizationException; +import com.linkedin.datahub.graphql.exception.DataHubGraphQLErrorCode; +import com.linkedin.datahub.graphql.exception.DataHubGraphQLException; import com.linkedin.datahub.graphql.generated.CreateDomainInput; import com.linkedin.datahub.graphql.generated.OwnerEntityType; import com.linkedin.datahub.graphql.generated.OwnershipType; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; import com.linkedin.domain.DomainProperties; import com.linkedin.entity.client.EntityClient; @@ -19,8 +23,11 @@ import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; + +import java.net.URISyntaxException; import java.util.UUID; import java.util.concurrent.CompletableFuture; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -45,9 +52,9 @@ public CompletableFuture get(DataFetchingEnvironment environment) throws final QueryContext context = environment.getContext(); final CreateDomainInput input = bindArgument(environment.getArgument("input"), CreateDomainInput.class); + final Urn parentDomain = input.getParentDomain() != null ? UrnUtils.getUrn(input.getParentDomain()) : null; return CompletableFuture.supplyAsync(() -> { - if (!AuthorizationUtils.canCreateDomains(context)) { throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator."); } @@ -64,6 +71,17 @@ public CompletableFuture get(DataFetchingEnvironment environment) throws throw new IllegalArgumentException("This Domain already exists!"); } + if (parentDomain != null && !_entityClient.exists(parentDomain, context.getAuthentication())) { + throw new IllegalArgumentException("Parent Domain does not exist!"); + } + + if (DomainUtils.hasNameConflict(input.getName(), parentDomain, context, _entityClient)) { + throw new DataHubGraphQLException( + String.format("\"%s\" already exists in this domain. Please pick a unique name.", input.getName()), + DataHubGraphQLErrorCode.CONFLICT + ); + } + // Create the MCP final MetadataChangeProposal proposal = buildMetadataChangeProposalWithKey(key, DOMAIN_ENTITY_NAME, DOMAIN_PROPERTIES_ASPECT_NAME, mapDomainProperties(input, context)); @@ -77,6 +95,8 @@ public CompletableFuture get(DataFetchingEnvironment environment) throws } OwnerUtils.addCreatorAsOwner(context, domainUrn, OwnerEntityType.CORP_USER, ownershipType, _entityService); return domainUrn; + } catch (DataHubGraphQLException e) { + throw e; } catch (Exception e) { log.error("Failed to create Domain with id: {}, name: {}: {}", input.getId(), input.getName(), e.getMessage()); throw new RuntimeException(String.format("Failed to create Domain with id: %s, name: %s", input.getId(), input.getName()), e); @@ -89,6 +109,13 @@ private DomainProperties mapDomainProperties(final CreateDomainInput input, fina result.setName(input.getName()); result.setDescription(input.getDescription(), SetMode.IGNORE_NULL); result.setCreated(new AuditStamp().setActor(UrnUtils.getUrn(context.getActorUrn())).setTime(System.currentTimeMillis())); + if (input.getParentDomain() != null) { + try { + result.setParentDomain(Urn.createFromString(input.getParentDomain())); + } catch (URISyntaxException e) { + throw new RuntimeException(String.format("Failed to create Domain Urn from string: %s", input.getParentDomain()), e); + } + } return result; } } \ No newline at end of file diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolver.java index 60a03fcddcc4dc..9ab90e8b4ff72c 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolver.java @@ -4,6 +4,7 @@ import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; import com.linkedin.datahub.graphql.exception.AuthorizationException; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.entity.client.EntityClient; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -32,6 +33,11 @@ public CompletableFuture get(final DataFetchingEnvironment environment) if (AuthorizationUtils.canManageDomains(context) || AuthorizationUtils.canDeleteEntity(urn, context)) { try { + // Make sure there are no child domains + if (DomainUtils.hasChildDomains(urn, context, _entityClient)) { + throw new RuntimeException(String.format("Cannot delete domain %s which has child domains", domainUrn)); + } + _entityClient.deleteEntity(urn, context.getAuthentication()); log.info(String.format("I've successfully deleted the entity %s with urn", domainUrn)); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java index 06bfa36fc3c146..0bf551c4683e61 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/DomainEntitiesResolver.java @@ -1,6 +1,5 @@ package com.linkedin.datahub.graphql.resolvers.domain; -import com.google.common.collect.ImmutableList; import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.generated.Domain; import com.linkedin.datahub.graphql.generated.DomainEntitiesInput; @@ -67,17 +66,22 @@ public CompletableFuture get(final DataFetchingEnvironment enviro try { + final CriterionArray criteria = new CriterionArray(); final Criterion filterCriterion = new Criterion() .setField(DOMAINS_FIELD_NAME + ".keyword") .setCondition(Condition.EQUAL) .setValue(urn); + criteria.add(filterCriterion); + if (input.getFilters() != null) { + input.getFilters().forEach(filter -> { + criteria.add(new Criterion().setField(filter.getField()).setValue(filter.getValue())); + }); + } return UrnSearchResultsMapper.map(_entityClient.searchAcrossEntities( SEARCHABLE_ENTITY_TYPES.stream().map(EntityTypeMapper::getName).collect(Collectors.toList()), query, - new Filter().setOr(new ConjunctiveCriterionArray( - new ConjunctiveCriterion().setAnd(new CriterionArray(ImmutableList.of(filterCriterion))) - )), + new Filter().setOr(new ConjunctiveCriterionArray(new ConjunctiveCriterion().setAnd(criteria))), start, count, null, diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolver.java index 6ed8639592d6e2..3a751e502eb10a 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolver.java @@ -1,22 +1,24 @@ package com.linkedin.datahub.graphql.resolvers.domain; import com.linkedin.common.urn.Urn; +import com.linkedin.common.urn.UrnUtils; import com.linkedin.datahub.graphql.QueryContext; -import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; -import com.linkedin.datahub.graphql.exception.AuthorizationException; import com.linkedin.datahub.graphql.generated.Domain; import com.linkedin.datahub.graphql.generated.EntityType; import com.linkedin.datahub.graphql.generated.ListDomainsInput; import com.linkedin.datahub.graphql.generated.ListDomainsResult; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.query.SearchFlags; +import com.linkedin.metadata.query.filter.Filter; import com.linkedin.metadata.query.filter.SortCriterion; import com.linkedin.metadata.query.filter.SortOrder; import com.linkedin.metadata.search.SearchEntity; import com.linkedin.metadata.search.SearchResult; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -30,7 +32,6 @@ * Resolver used for listing all Domains defined within DataHub. Requires the MANAGE_DOMAINS platform privilege. */ public class ListDomainsResolver implements DataFetcher> { - private static final Integer DEFAULT_START = 0; private static final Integer DEFAULT_COUNT = 20; private static final String DEFAULT_QUERY = ""; @@ -48,18 +49,19 @@ public CompletableFuture get(final DataFetchingEnvironment en return CompletableFuture.supplyAsync(() -> { - if (AuthorizationUtils.canCreateDomains(context)) { final ListDomainsInput input = bindArgument(environment.getArgument("input"), ListDomainsInput.class); final Integer start = input.getStart() == null ? DEFAULT_START : input.getStart(); final Integer count = input.getCount() == null ? DEFAULT_COUNT : input.getCount(); final String query = input.getQuery() == null ? DEFAULT_QUERY : input.getQuery(); + final Urn parentDomainUrn = input.getParentDomain() != null ? UrnUtils.getUrn(input.getParentDomain()) : null; + final Filter filter = DomainUtils.buildParentDomainFilter(parentDomainUrn); try { - // First, get all group Urns. + // First, get all domain Urns. final SearchResult gmsResult = _entityClient.search( Constants.DOMAIN_ENTITY_NAME, query, - null, + filter, new SortCriterion().setField(DOMAIN_CREATED_TIME_INDEX_FIELD_NAME).setOrder(SortOrder.DESCENDING), start, count, @@ -78,8 +80,6 @@ public CompletableFuture get(final DataFetchingEnvironment en } catch (Exception e) { throw new RuntimeException("Failed to list domains", e); } - } - throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator."); }); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/ParentDomainsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/ParentDomainsResolver.java new file mode 100644 index 00000000000000..dcaa7d61ed90cd --- /dev/null +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/ParentDomainsResolver.java @@ -0,0 +1,59 @@ +package com.linkedin.datahub.graphql.resolvers.domain; + +import com.linkedin.common.urn.Urn; +import com.linkedin.common.urn.UrnUtils; +import com.linkedin.datahub.graphql.QueryContext; +import com.linkedin.datahub.graphql.generated.Entity; +import com.linkedin.datahub.graphql.generated.ParentDomainsResult; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; +import com.linkedin.entity.client.EntityClient; +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import static com.linkedin.metadata.Constants.DOMAIN_ENTITY_NAME; + +public class ParentDomainsResolver implements DataFetcher> { + + private final EntityClient _entityClient; + + public ParentDomainsResolver(final EntityClient entityClient) { + _entityClient = entityClient; + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) { + final QueryContext context = environment.getContext(); + final Urn urn = UrnUtils.getUrn(((Entity) environment.getSource()).getUrn()); + final List parentDomains = new ArrayList<>(); + final Set visitedParentUrns = new HashSet<>(); + + if (!DOMAIN_ENTITY_NAME.equals(urn.getEntityType())) { + throw new IllegalArgumentException(String.format("Failed to resolve parents for entity type %s", urn)); + } + + return CompletableFuture.supplyAsync(() -> { + try { + Entity parentDomain = DomainUtils.getParentDomain(urn, context, _entityClient); + + while (parentDomain != null && !visitedParentUrns.contains(parentDomain.getUrn())) { + parentDomains.add(parentDomain); + visitedParentUrns.add(parentDomain.getUrn()); + parentDomain = DomainUtils.getParentDomain(Urn.createFromString(parentDomain.getUrn()), context, _entityClient); + } + + final ParentDomainsResult result = new ParentDomainsResult(); + result.setCount(parentDomains.size()); + result.setDomains(parentDomains); + return result; + } catch (Exception e) { + throw new RuntimeException(String.format("Failed to load parent domains for entity %s", urn), e); + } + }); + } +} diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/MoveDomainResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/MoveDomainResolver.java new file mode 100644 index 00000000000000..e5e3a5a0ee42e3 --- /dev/null +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/MoveDomainResolver.java @@ -0,0 +1,89 @@ +package com.linkedin.datahub.graphql.resolvers.mutate; + +import com.linkedin.common.urn.CorpuserUrn; +import com.linkedin.common.urn.Urn; +import com.linkedin.common.urn.UrnUtils; +import com.linkedin.data.template.SetMode; +import com.linkedin.datahub.graphql.QueryContext; +import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; +import com.linkedin.datahub.graphql.exception.AuthorizationException; +import com.linkedin.datahub.graphql.exception.DataHubGraphQLErrorCode; +import com.linkedin.datahub.graphql.exception.DataHubGraphQLException; +import com.linkedin.datahub.graphql.generated.MoveDomainInput; +import com.linkedin.datahub.graphql.resolvers.ResolverUtils; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; +import com.linkedin.domain.DomainProperties; +import com.linkedin.entity.client.EntityClient; +import com.linkedin.metadata.Constants; +import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.EntityUtils; +import graphql.schema.DataFetcher; +import graphql.schema.DataFetchingEnvironment; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.CompletableFuture; + +@Slf4j +@RequiredArgsConstructor +public class MoveDomainResolver implements DataFetcher> { + + private final EntityService _entityService; + private final EntityClient _entityClient; + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + final MoveDomainInput input = ResolverUtils.bindArgument(environment.getArgument("input"), MoveDomainInput.class); + final QueryContext context = environment.getContext(); + final Urn resourceUrn = UrnUtils.getUrn(input.getResourceUrn()); + final Urn newParentDomainUrn = input.getParentDomain() != null ? UrnUtils.getUrn(input.getParentDomain()) : null; + + return CompletableFuture.supplyAsync(() -> { + if (!AuthorizationUtils.canManageDomains(context)) { + throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator."); + } + + try { + if (!resourceUrn.getEntityType().equals(Constants.DOMAIN_ENTITY_NAME)) { + throw new IllegalArgumentException("Resource is not a domain."); + } + + DomainProperties properties = (DomainProperties) EntityUtils.getAspectFromEntity( + resourceUrn.toString(), + Constants.DOMAIN_PROPERTIES_ASPECT_NAME, _entityService, + null + ); + + if (properties == null) { + throw new IllegalArgumentException("Domain properties do not exist."); + } + + if (newParentDomainUrn != null) { + if (!newParentDomainUrn.getEntityType().equals(Constants.DOMAIN_ENTITY_NAME)) { + throw new IllegalArgumentException("Parent entity is not a domain."); + } + if (!_entityService.exists(newParentDomainUrn)) { + throw new IllegalArgumentException("Parent entity does not exist."); + } + } + + if (DomainUtils.hasNameConflict(properties.getName(), newParentDomainUrn, context, _entityClient)) { + throw new DataHubGraphQLException( + String.format("\"%s\" already exists in the destination domain. Please pick a unique name.", properties.getName()), + DataHubGraphQLErrorCode.CONFLICT + ); + } + + properties.setParentDomain(newParentDomainUrn, SetMode.REMOVE_IF_NULL); + Urn actor = CorpuserUrn.createFromString(context.getActorUrn()); + MutationUtils.persistAspect(resourceUrn, Constants.DOMAIN_PROPERTIES_ASPECT_NAME, properties, actor, _entityService); + return true; + } catch (DataHubGraphQLException e) { + throw e; + } catch (Exception e) { + log.error("Failed to move domain {} to parent {} : {}", input.getResourceUrn(), input.getParentDomain(), e.getMessage()); + throw new RuntimeException(String.format("Failed to move domain %s to %s", input.getResourceUrn(), input.getParentDomain()), e); + } + }); + } +} diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java index 225bee54142c4c..0e316ac1296ee0 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java @@ -6,8 +6,11 @@ import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; import com.linkedin.datahub.graphql.exception.AuthorizationException; +import com.linkedin.datahub.graphql.exception.DataHubGraphQLErrorCode; +import com.linkedin.datahub.graphql.exception.DataHubGraphQLException; import com.linkedin.datahub.graphql.generated.UpdateNameInput; import com.linkedin.datahub.graphql.resolvers.dataproduct.DataProductAuthorizationUtils; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils; import com.linkedin.dataproduct.DataProductProperties; import com.linkedin.domain.DomainProperties; @@ -124,14 +127,25 @@ private Boolean updateDomainName( try { DomainProperties domainProperties = (DomainProperties) EntityUtils.getAspectFromEntity( targetUrn.toString(), Constants.DOMAIN_PROPERTIES_ASPECT_NAME, _entityService, null); + if (domainProperties == null) { throw new IllegalArgumentException("Domain does not exist"); } + + if (DomainUtils.hasNameConflict(input.getName(), DomainUtils.getParentDomainSafely(domainProperties), context, _entityClient)) { + throw new DataHubGraphQLException( + String.format("\"%s\" already exists in this domain. Please pick a unique name.", input.getName()), + DataHubGraphQLErrorCode.CONFLICT + ); + } + domainProperties.setName(input.getName()); Urn actor = CorpuserUrn.createFromString(context.getActorUrn()); persistAspect(targetUrn, Constants.DOMAIN_PROPERTIES_ASPECT_NAME, domainProperties, actor, _entityService); return true; + } catch (DataHubGraphQLException e) { + throw e; } catch (Exception e) { throw new RuntimeException(String.format("Failed to perform update against input %s", input), e); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java index b57160be09d326..585fbdf53a2ba4 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java @@ -5,29 +5,55 @@ import com.linkedin.common.UrnArray; import com.linkedin.common.urn.Urn; import com.linkedin.common.urn.UrnUtils; +import com.linkedin.data.DataMap; import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; import com.datahub.authorization.ConjunctivePrivilegeGroup; import com.datahub.authorization.DisjunctivePrivilegeGroup; +import com.linkedin.datahub.graphql.generated.Entity; import com.linkedin.datahub.graphql.generated.ResourceRefInput; +import com.linkedin.datahub.graphql.types.common.mappers.UrnToEntityMapper; +import com.linkedin.domain.DomainProperties; import com.linkedin.domain.Domains; +import com.linkedin.entity.EntityResponse; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.authorization.PoliciesConfig; import com.linkedin.metadata.entity.EntityService; import com.linkedin.metadata.entity.EntityUtils; +import com.linkedin.metadata.query.filter.Condition; +import com.linkedin.metadata.query.filter.ConjunctiveCriterion; +import com.linkedin.metadata.query.filter.ConjunctiveCriterionArray; +import com.linkedin.metadata.query.filter.Criterion; +import com.linkedin.metadata.query.filter.CriterionArray; +import com.linkedin.metadata.query.filter.Filter; +import com.linkedin.metadata.search.SearchEntity; +import com.linkedin.metadata.search.SearchResult; import com.linkedin.mxe.MetadataChangeProposal; + +import com.linkedin.r2.RemoteInvocationException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; + import lombok.extern.slf4j.Slf4j; import static com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils.*; +import static com.linkedin.metadata.Constants.*; // TODO: Move to consuming from DomainService. @Slf4j public class DomainUtils { + private static final String PARENT_DOMAIN_INDEX_FIELD_NAME = "parentDomain.keyword"; + private static final String HAS_PARENT_DOMAIN_INDEX_FIELD_NAME = "hasParentDomain"; + private static final String NAME_INDEX_FIELD_NAME = "name"; + private static final ConjunctivePrivilegeGroup ALL_PRIVILEGES_GROUP = new ConjunctivePrivilegeGroup(ImmutableList.of( PoliciesConfig.EDIT_ENTITY_PRIVILEGE.getType() )); @@ -85,4 +111,200 @@ public static void validateDomain(Urn domainUrn, EntityService entityService) { throw new IllegalArgumentException(String.format("Failed to validate Domain with urn %s. Urn does not exist.", domainUrn)); } } + + private static List buildRootDomainCriteria() { + final List criteria = new ArrayList<>(); + + criteria.add( + new Criterion() + .setField(HAS_PARENT_DOMAIN_INDEX_FIELD_NAME) + .setValue("false") + .setCondition(Condition.EQUAL) + ); + criteria.add( + new Criterion() + .setField(HAS_PARENT_DOMAIN_INDEX_FIELD_NAME) + .setValue("") + .setCondition(Condition.IS_NULL) + ); + + return criteria; + } + + private static List buildParentDomainCriteria(@Nonnull final Urn parentDomainUrn) { + final List criteria = new ArrayList<>(); + + criteria.add( + new Criterion() + .setField(HAS_PARENT_DOMAIN_INDEX_FIELD_NAME) + .setValue("true") + .setCondition(Condition.EQUAL) + ); + criteria.add( + new Criterion() + .setField(PARENT_DOMAIN_INDEX_FIELD_NAME) + .setValue(parentDomainUrn.toString()) + .setCondition(Condition.EQUAL) + ); + + return criteria; + } + + private static Criterion buildNameCriterion(@Nonnull final String name) { + return new Criterion() + .setField(NAME_INDEX_FIELD_NAME) + .setValue(name) + .setCondition(Condition.EQUAL); + } + + /** + * Builds a filter that ORs together the root parent criterion / ANDs together the parent domain criterion. + * The reason for the OR on root is elastic can have a null|false value to represent an root domain in the index. + * @param name an optional name to AND in to each condition of the filter + * @param parentDomainUrn the parent domain (null means root). + * @return the Filter + */ + public static Filter buildNameAndParentDomainFilter(@Nullable final String name, @Nullable final Urn parentDomainUrn) { + if (parentDomainUrn == null) { + return new Filter().setOr( + new ConjunctiveCriterionArray( + buildRootDomainCriteria().stream().map(parentCriterion -> { + final CriterionArray array = new CriterionArray(parentCriterion); + if (name != null) { + array.add(buildNameCriterion(name)); + } + return new ConjunctiveCriterion().setAnd(array); + }).collect(Collectors.toList()) + ) + ); + } + + final CriterionArray andArray = new CriterionArray(buildParentDomainCriteria(parentDomainUrn)); + if (name != null) { + andArray.add(buildNameCriterion(name)); + } + return new Filter().setOr( + new ConjunctiveCriterionArray( + new ConjunctiveCriterion().setAnd(andArray) + ) + ); + } + + public static Filter buildParentDomainFilter(@Nullable final Urn parentDomainUrn) { + return buildNameAndParentDomainFilter(null, parentDomainUrn); + } + + /** + * Check if a domain has any child domains + * @param domainUrn the URN of the domain to check + * @param context query context (includes authorization context to authorize the request) + * @param entityClient client used to perform the check + * @return true if the domain has any child domains, false if it does not + */ + public static boolean hasChildDomains( + @Nonnull final Urn domainUrn, + @Nonnull final QueryContext context, + @Nonnull final EntityClient entityClient + ) throws RemoteInvocationException { + Filter parentDomainFilter = buildParentDomainFilter(domainUrn); + // Search for entities matching parent domain + // Limit count to 1 for existence check + final SearchResult searchResult = entityClient.filter( + DOMAIN_ENTITY_NAME, + parentDomainFilter, + null, + 0, + 1, + context.getAuthentication()); + return (searchResult.getNumEntities() > 0); + } + + private static Map getDomainsByNameAndParent( + @Nonnull final String name, + @Nullable final Urn parentDomainUrn, + @Nonnull final QueryContext context, + @Nonnull final EntityClient entityClient + ) { + try { + final Filter filter = buildNameAndParentDomainFilter(name, parentDomainUrn); + + final SearchResult searchResult = entityClient.filter( + DOMAIN_ENTITY_NAME, + filter, + null, + 0, + 1000, + context.getAuthentication()); + + final Set domainUrns = searchResult.getEntities() + .stream() + .map(SearchEntity::getEntity) + .collect(Collectors.toSet()); + + return entityClient.batchGetV2( + DOMAIN_ENTITY_NAME, + domainUrns, + Collections.singleton(DOMAIN_PROPERTIES_ASPECT_NAME), + context.getAuthentication()); + } catch (Exception e) { + throw new RuntimeException("Failed fetching Domains by name and parent", e); + } + } + + public static boolean hasNameConflict( + @Nonnull final String name, + @Nullable final Urn parentDomainUrn, + @Nonnull final QueryContext context, + @Nonnull final EntityClient entityClient + ) { + final Map entities = getDomainsByNameAndParent(name, parentDomainUrn, context, entityClient); + + // Even though we searched by name, do one more pass to check the name is unique + return entities.values().stream().anyMatch(entityResponse -> { + if (entityResponse.getAspects().containsKey(DOMAIN_PROPERTIES_ASPECT_NAME)) { + DataMap dataMap = entityResponse.getAspects().get(DOMAIN_PROPERTIES_ASPECT_NAME).getValue().data(); + DomainProperties domainProperties = new DomainProperties(dataMap); + return (domainProperties.hasName() && domainProperties.getName().equals(name)); + } + return false; + }); + } + + @Nullable + public static Entity getParentDomain( + @Nonnull final Urn urn, + @Nonnull final QueryContext context, + @Nonnull final EntityClient entityClient + ) { + try { + final EntityResponse entityResponse = entityClient.getV2( + DOMAIN_ENTITY_NAME, + urn, + Collections.singleton(DOMAIN_PROPERTIES_ASPECT_NAME), + context.getAuthentication() + ); + + if (entityResponse != null && entityResponse.getAspects().containsKey(DOMAIN_PROPERTIES_ASPECT_NAME)) { + final DomainProperties properties = new DomainProperties(entityResponse.getAspects().get(DOMAIN_PROPERTIES_ASPECT_NAME).getValue().data()); + final Urn parentDomainUrn = getParentDomainSafely(properties); + return parentDomainUrn != null ? UrnToEntityMapper.map(parentDomainUrn) : null; + } + } catch (Exception e) { + throw new RuntimeException(String.format("Failed to retrieve parent domain for entity %s", urn), e); + } + + return null; + } + + /** + * Get a parent domain only if hasParentDomain was set. There is strange elastic behavior where moving a domain + * to the root leaves the parentDomain field set but makes hasParentDomain false. This helper makes sure that queries + * to elastic where hasParentDomain=false and parentDomain=value only gives us the parentDomain if hasParentDomain=true. + * @param properties the domain properties aspect + * @return the parentDomain or null + */ + @Nullable + public static Urn getParentDomainSafely(@Nonnull final DomainProperties properties) { + return properties.hasParentDomain() ? properties.getParentDomain() : null; + } } \ No newline at end of file diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/post/DeletePostResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/post/DeletePostResolver.java index cd2a3dda70033a..d3cd0126fb8527 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/post/DeletePostResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/post/DeletePostResolver.java @@ -23,7 +23,7 @@ public class DeletePostResolver implements DataFetcher get(final DataFetchingEnvironment environment) throws Exception { final QueryContext context = environment.getContext(); - if (!AuthorizationUtils.canCreateGlobalAnnouncements(context)) { + if (!AuthorizationUtils.canManageGlobalAnnouncements(context)) { throw new AuthorizationException( "Unauthorized to delete posts. Please contact your DataHub administrator if this needs corrective action."); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchUtils.java index e40bbca56b4167..fb146ef72877d1 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/search/SearchUtils.java @@ -68,12 +68,12 @@ private SearchUtils() { EntityType.GLOSSARY_TERM, EntityType.GLOSSARY_NODE, EntityType.TAG, + EntityType.ROLE, EntityType.CORP_USER, EntityType.CORP_GROUP, EntityType.CONTAINER, EntityType.DOMAIN, EntityType.DATA_PRODUCT, - EntityType.ROLE, EntityType.NOTEBOOK); @@ -95,6 +95,7 @@ private SearchUtils() { EntityType.TAG, EntityType.CORP_USER, EntityType.CORP_GROUP, + EntityType.ROLE, EntityType.NOTEBOOK, EntityType.DATA_PRODUCT); @@ -387,4 +388,4 @@ public static List getEntityNames(List inputTypes) { (inputTypes == null || inputTypes.isEmpty()) ? SEARCHABLE_ENTITY_TYPES : inputTypes; return entityTypes.stream().map(EntityTypeMapper::getName).collect(Collectors.toList()); } -} +} \ No newline at end of file diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/chart/mappers/ChartMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/chart/mappers/ChartMapper.java index 9e03bf19889d10..657c9b688aed20 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/chart/mappers/ChartMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/chart/mappers/ChartMapper.java @@ -68,7 +68,7 @@ public Chart apply(@Nonnull final EntityResponse entityResponse) { result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.CHART); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/SearchFlagsInputMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/SearchFlagsInputMapper.java index 6435d6ee4c8e55..f3ac008734339e 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/SearchFlagsInputMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/SearchFlagsInputMapper.java @@ -39,6 +39,9 @@ public com.linkedin.metadata.query.SearchFlags apply(@Nonnull final SearchFlags if (searchFlags.getSkipAggregates() != null) { result.setSkipAggregates(searchFlags.getSkipAggregates()); } + if (searchFlags.getGetSuggestions() != null) { + result.setGetSuggestions(searchFlags.getGetSuggestions()); + } return result; } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/util/RunInfo.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/util/RunInfo.java new file mode 100644 index 00000000000000..7d1b374e1f9b6c --- /dev/null +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/util/RunInfo.java @@ -0,0 +1,16 @@ +package com.linkedin.datahub.graphql.types.common.mappers.util; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + + +@Data +@Setter +@Getter +@AllArgsConstructor +public class RunInfo { + private final String id; + private final Long time; +} diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/util/SystemMetadataUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/util/SystemMetadataUtils.java index 731f4e85e0663a..d08300d648c323 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/util/SystemMetadataUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/common/mappers/util/SystemMetadataUtils.java @@ -3,7 +3,10 @@ import com.linkedin.entity.EnvelopedAspectMap; import com.linkedin.mxe.SystemMetadata; +import java.util.ArrayList; +import java.util.List; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import static com.linkedin.metadata.Constants.DEFAULT_RUN_ID; @@ -12,19 +15,48 @@ public class SystemMetadataUtils { private SystemMetadataUtils() { } - public static Long getLastIngested(@Nonnull EnvelopedAspectMap aspectMap) { - Long lastIngested = null; + @Nullable + public static Long getLastIngestedTime(@Nonnull EnvelopedAspectMap aspectMap) { + RunInfo lastIngestionRun = getLastIngestionRun(aspectMap); + return lastIngestionRun != null ? lastIngestionRun.getTime() : null; + } + + @Nullable + public static String getLastIngestedRunId(@Nonnull EnvelopedAspectMap aspectMap) { + RunInfo lastIngestionRun = getLastIngestionRun(aspectMap); + return lastIngestionRun != null ? lastIngestionRun.getId() : null; + } + + /** + * Returns a sorted list of all of the most recent ingestion runs based on the most recent aspects present for the entity. + */ + @Nonnull + public static List getLastIngestionRuns(@Nonnull EnvelopedAspectMap aspectMap) { + final List runs = new ArrayList<>(); for (String aspect : aspectMap.keySet()) { if (aspectMap.get(aspect).hasSystemMetadata()) { SystemMetadata systemMetadata = aspectMap.get(aspect).getSystemMetadata(); - if (systemMetadata.hasRunId() && !systemMetadata.getRunId().equals(DEFAULT_RUN_ID) && systemMetadata.hasLastObserved()) { + if (systemMetadata.hasLastRunId() && !systemMetadata.getLastRunId().equals(DEFAULT_RUN_ID) && systemMetadata.hasLastObserved()) { Long lastObserved = systemMetadata.getLastObserved(); - if (lastIngested == null || lastObserved > lastIngested) { - lastIngested = lastObserved; - } + String runId = systemMetadata.getLastRunId(); + RunInfo run = new RunInfo(runId, lastObserved); + runs.add(run); + } else if (systemMetadata.hasRunId() && !systemMetadata.getRunId().equals(DEFAULT_RUN_ID) && systemMetadata.hasLastObserved()) { + // Handle the legacy case: Check original run ids. + Long lastObserved = systemMetadata.getLastObserved(); + String runId = systemMetadata.getRunId(); + RunInfo run = new RunInfo(runId, lastObserved); + runs.add(run); } } } - return lastIngested; + runs.sort((a, b) -> Long.compare(b.getTime(), a.getTime())); + return runs; + } + + @Nullable + private static RunInfo getLastIngestionRun(@Nonnull EnvelopedAspectMap aspectMap) { + List runs = getLastIngestionRuns(aspectMap); + return !runs.isEmpty() ? runs.get(0) : null; // Just take the first, to get the most recent run. } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/container/mappers/ContainerMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/container/mappers/ContainerMapper.java index ec559a569920d5..aeaa8f4f85c144 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/container/mappers/ContainerMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/container/mappers/ContainerMapper.java @@ -42,7 +42,7 @@ public static Container map(final EntityResponse entityResponse) { final Container result = new Container(); final Urn entityUrn = entityResponse.getUrn(); final EnvelopedAspectMap aspects = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspects); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspects); result.setLastIngested(lastIngested); result.setUrn(entityUrn.toString()); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dashboard/mappers/DashboardMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dashboard/mappers/DashboardMapper.java index 38e2cacbde668e..32e4341ece4aac 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dashboard/mappers/DashboardMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dashboard/mappers/DashboardMapper.java @@ -67,7 +67,7 @@ public Dashboard apply(@Nonnull final EntityResponse entityResponse) { result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.DASHBOARD); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataflow/mappers/DataFlowMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataflow/mappers/DataFlowMapper.java index 98debe08cf36b6..719fa9f0b2bf01 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataflow/mappers/DataFlowMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataflow/mappers/DataFlowMapper.java @@ -57,7 +57,7 @@ public DataFlow apply(@Nonnull final EntityResponse entityResponse) { Urn entityUrn = entityResponse.getUrn(); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/datajob/mappers/DataJobMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/datajob/mappers/DataJobMapper.java index 208a85acfe42ec..4845fc18763488 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/datajob/mappers/DataJobMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/datajob/mappers/DataJobMapper.java @@ -60,7 +60,7 @@ public DataJob apply(@Nonnull final EntityResponse entityResponse) { result.setType(EntityType.DATA_JOB); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); entityResponse.getAspects().forEach((name, aspect) -> { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/mappers/DataPlatformMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/mappers/DataPlatformMapper.java index 0f4b90cd6b3b44..8df44e8f6e9e98 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/mappers/DataPlatformMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/mappers/DataPlatformMapper.java @@ -35,7 +35,7 @@ public DataPlatform apply(@Nonnull final EntityResponse entityResponse) { result.setName(dataPlatformKey.getPlatformName()); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataproduct/mappers/DataProductMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataproduct/mappers/DataProductMapper.java index 9cb6840067e7b8..254b43ecb96ccb 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataproduct/mappers/DataProductMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataproduct/mappers/DataProductMapper.java @@ -50,7 +50,8 @@ public DataProduct apply(@Nonnull final EntityResponse entityResponse) { EnvelopedAspectMap aspectMap = entityResponse.getAspects(); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); - mappingHelper.mapToResult(DATA_PRODUCT_PROPERTIES_ASPECT_NAME, this::mapDataProductProperties); + mappingHelper.mapToResult(DATA_PRODUCT_PROPERTIES_ASPECT_NAME, (dataProduct, dataMap) -> + mapDataProductProperties(dataProduct, dataMap, entityUrn)); mappingHelper.mapToResult(GLOBAL_TAGS_ASPECT_NAME, (dataProduct, dataMap) -> dataProduct.setTags(GlobalTagsMapper.map(new GlobalTags(dataMap), entityUrn))); mappingHelper.mapToResult(GLOSSARY_TERMS_ASPECT_NAME, (dataProduct, dataMap) -> @@ -65,11 +66,12 @@ public DataProduct apply(@Nonnull final EntityResponse entityResponse) { return result; } - private void mapDataProductProperties(@Nonnull DataProduct dataProduct, @Nonnull DataMap dataMap) { + private void mapDataProductProperties(@Nonnull DataProduct dataProduct, @Nonnull DataMap dataMap, @Nonnull Urn urn) { DataProductProperties dataProductProperties = new DataProductProperties(dataMap); com.linkedin.datahub.graphql.generated.DataProductProperties properties = new com.linkedin.datahub.graphql.generated.DataProductProperties(); - properties.setName(dataProductProperties.getName()); + final String name = dataProductProperties.hasName() ? dataProductProperties.getName() : urn.getId(); + properties.setName(name); properties.setDescription(dataProductProperties.getDescription()); if (dataProductProperties.hasExternalUrl()) { properties.setExternalUrl(dataProductProperties.getExternalUrl().toString()); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataset/mappers/DatasetMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataset/mappers/DatasetMapper.java index f0899f8fbc0cb0..4867aa1d89825f 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataset/mappers/DatasetMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataset/mappers/DatasetMapper.java @@ -75,7 +75,7 @@ public Dataset apply(@Nonnull final EntityResponse entityResponse) { result.setType(EntityType.DATASET); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); @@ -145,6 +145,9 @@ private void mapDatasetProperties(@Nonnull Dataset dataset, @Nonnull DataMap dat properties.setQualifiedName(gmsProperties.getQualifiedName()); dataset.setProperties(properties); dataset.setDescription(properties.getDescription()); + if (gmsProperties.getUri() != null) { + dataset.setUri(gmsProperties.getUri().toString()); + } TimeStamp created = gmsProperties.getCreated(); if (created != null) { properties.setCreated(created.getTime()); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java index 0b292a373ea40e..5ba32b0c2a77c1 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/MapperUtils.java @@ -1,12 +1,18 @@ package com.linkedin.datahub.graphql.types.mappers; +import com.linkedin.common.urn.Urn; import com.linkedin.datahub.graphql.generated.AggregationMetadata; import com.linkedin.datahub.graphql.generated.FacetMetadata; import com.linkedin.datahub.graphql.generated.MatchedField; import com.linkedin.datahub.graphql.generated.SearchResult; +import com.linkedin.datahub.graphql.generated.SearchSuggestion; import com.linkedin.datahub.graphql.resolvers.EntityTypeMapper; import com.linkedin.datahub.graphql.types.common.mappers.UrnToEntityMapper; import com.linkedin.metadata.search.SearchEntity; +import com.linkedin.metadata.search.utils.SearchUtils; +import lombok.extern.slf4j.Slf4j; + +import java.net.URISyntaxException; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -16,6 +22,7 @@ import static com.linkedin.metadata.utils.SearchUtil.*; +@Slf4j public class MapperUtils { private MapperUtils() { @@ -54,7 +61,24 @@ public static String convertFilterValue(String filterValue, List isEnti public static List getMatchedFieldEntry(List highlightMetadata) { return highlightMetadata.stream() - .map(field -> new MatchedField(field.getName(), field.getValue())) + .map(field -> { + MatchedField matchedField = new MatchedField(); + matchedField.setName(field.getName()); + matchedField.setValue(field.getValue()); + if (SearchUtils.isUrn(field.getValue())) { + try { + Urn urn = Urn.createFromString(field.getValue()); + matchedField.setEntity(UrnToEntityMapper.map(urn)); + } catch (URISyntaxException e) { + log.warn("Failed to create urn from MatchedField value: {}", field.getValue(), e); + } + } + return matchedField; + }) .collect(Collectors.toList()); } + + public static SearchSuggestion mapSearchSuggestion(com.linkedin.metadata.search.SearchSuggestion suggestion) { + return new SearchSuggestion(suggestion.getText(), suggestion.getScore(), Math.toIntExact(suggestion.getFrequency())); + } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/UrnSearchResultsMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/UrnSearchResultsMapper.java index 9f750820e30935..b16e2f10d1df7a 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/UrnSearchResultsMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mappers/UrnSearchResultsMapper.java @@ -27,6 +27,7 @@ public SearchResults apply(com.linkedin.metadata.search.SearchResult input) { final SearchResultMetadata searchResultMetadata = input.getMetadata(); result.setSearchResults(input.getEntities().stream().map(MapperUtils::mapResult).collect(Collectors.toList())); result.setFacets(searchResultMetadata.getAggregations().stream().map(MapperUtils::mapFacet).collect(Collectors.toList())); + result.setSuggestions(searchResultMetadata.getSuggestions().stream().map(MapperUtils::mapSearchSuggestion).collect(Collectors.toList())); return result; } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureMapper.java index c924384756ac88..010ae477251f39 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureMapper.java @@ -60,7 +60,7 @@ public MLFeature apply(@Nonnull final EntityResponse entityResponse) { result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.MLFEATURE); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureTableMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureTableMapper.java index f0e7cffe5578d9..3ba9a76c4bdde1 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureTableMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLFeatureTableMapper.java @@ -59,7 +59,7 @@ public MLFeatureTable apply(@Nonnull final EntityResponse entityResponse) { result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.MLFEATURE_TABLE); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelGroupMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelGroupMapper.java index 52db5468e00910..311ee121bcaf98 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelGroupMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelGroupMapper.java @@ -57,7 +57,7 @@ public MLModelGroup apply(@Nonnull final EntityResponse entityResponse) { result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.MLMODEL_GROUP); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelMapper.java index 414ba5d196d6b3..0c2eeabe5701d9 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLModelMapper.java @@ -71,7 +71,7 @@ public MLModel apply(@Nonnull final EntityResponse entityResponse) { result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.MLMODEL); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLPrimaryKeyMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLPrimaryKeyMapper.java index 533c0f60a930ab..0bd5db4d884ae4 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLPrimaryKeyMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/mlmodel/mappers/MLPrimaryKeyMapper.java @@ -56,7 +56,7 @@ public MLPrimaryKey apply(@Nonnull final EntityResponse entityResponse) { result.setUrn(entityResponse.getUrn().toString()); result.setType(EntityType.MLPRIMARY_KEY); EnvelopedAspectMap aspectMap = entityResponse.getAspects(); - Long lastIngested = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastIngested = SystemMetadataUtils.getLastIngestedTime(aspectMap); result.setLastIngested(lastIngested); MappingHelper mappingHelper = new MappingHelper<>(aspectMap, result); diff --git a/datahub-graphql-core/src/main/resources/app.graphql b/datahub-graphql-core/src/main/resources/app.graphql index 37183bac13f0eb..075a3b0fac43bc 100644 --- a/datahub-graphql-core/src/main/resources/app.graphql +++ b/datahub-graphql-core/src/main/resources/app.graphql @@ -125,6 +125,11 @@ type PlatformPrivileges { Whether the user should be able to create, update, and delete ownership types. """ manageOwnershipTypes: Boolean! + + """ + Whether the user can create and delete posts pinned to the home page. + """ + manageGlobalAnnouncements: Boolean! } """ @@ -216,6 +221,11 @@ type VisualConfig { Configuration for the queries tab """ entityProfiles: EntityProfilesConfig + + """ + Configuration for search results + """ + searchResult: SearchResultsVisualConfig } """ @@ -250,6 +260,16 @@ type EntityProfileConfig { defaultTab: String } +""" +Configuration for a search result +""" +type SearchResultsVisualConfig { + """ + Whether a search result should highlight the name/description if it was matched on those fields. + """ + enableNameHighlight: Boolean +} + """ Configurations related to tracking users in the app """ @@ -421,6 +441,17 @@ type FeatureFlagsConfig { Whether we should show CTAs in the UI related to moving to Managed DataHub by Acryl. """ showAcrylInfo: Boolean! + + """ + Whether we should show AccessManagement tab in the datahub UI. + """ + showAccessManagement: Boolean! + + """ + Enables the nested Domains feature that allows users to have sub-Domains. + If this is off, Domains appear "flat" again. + """ + nestedDomainsEnabled: Boolean! } """ diff --git a/datahub-graphql-core/src/main/resources/entity.graphql b/datahub-graphql-core/src/main/resources/entity.graphql index b1f9d57300177f..39f86948c77c40 100644 --- a/datahub-graphql-core/src/main/resources/entity.graphql +++ b/datahub-graphql-core/src/main/resources/entity.graphql @@ -68,6 +68,10 @@ type Query { Fetch a Tag by primary key (urn) """ tag(urn: String!): Tag + """ + Fetch a Role by primary key (urn) + """ + role(urn: String!): Role """ Fetch a Glossary Term by primary key (urn) @@ -430,6 +434,11 @@ type Mutation { """ createDomain(input: CreateDomainInput!): String + """ + Moves a domain to be parented under another domain. + """ + moveDomain(input: MoveDomainInput!): Boolean + """ Delete a Domain """ @@ -1451,12 +1460,12 @@ type Role implements Entity { """ Role properties to include Request Access Url """ - properties: RoleProperties! + properties: RoleProperties """ A standard Entity Type """ - actors: Actor! + actors: Actor } @@ -7731,6 +7740,21 @@ input UpdateParentNodeInput { resourceUrn: String! } +""" +Input for updating the parent domain of a domain. +""" +input MoveDomainInput { + """ + The new parent domain urn. If parentDomain is null, this will remove the parent from this entity + """ + parentDomain: String + + """ + The primary key of the resource to update the parent domain for + """ + resourceUrn: String! +} + """ Input for updating the name of an entity """ @@ -9580,15 +9604,31 @@ type Domain implements Entity { """ entities(input: DomainEntitiesInput): SearchResults + """ + Recursively get the lineage of parent domains for this entity + """ + parentDomains: ParentDomainsResult + """ Edges extending from this entity """ relationships(input: RelationshipsInput!): EntityRelationshipsResult } +""" +All of the parent domains starting from a single Domain through all of its ancestors +""" +type ParentDomainsResult { + """ + The number of parent domains bubbling up for this entity + """ + count: Int! - - + """ + A list of parent domains in order from direct parent, to parent's parent etc. If there are no parents, return an empty list + """ + domains: [Entity!]! +} """ Properties about a domain @@ -9648,6 +9688,11 @@ input CreateDomainInput { Optional description for the Domain """ description: String + + """ + Optional parent domain urn for the domain + """ + parentDomain: String } """ @@ -9668,6 +9713,11 @@ input ListDomainsInput { Optional search query """ query: String + + """ + Optional parent domain + """ + parentDomain: String } """ @@ -11164,4 +11214,4 @@ input UpdateOwnershipTypeInput { The description of the Custom Ownership Type """ description: String -} +} \ No newline at end of file diff --git a/datahub-graphql-core/src/main/resources/search.graphql b/datahub-graphql-core/src/main/resources/search.graphql index fbea66f7389553..4cabdb04afe77c 100644 --- a/datahub-graphql-core/src/main/resources/search.graphql +++ b/datahub-graphql-core/src/main/resources/search.graphql @@ -138,6 +138,11 @@ input SearchFlags { Whether to skip aggregates/facets """ skipAggregates: Boolean + + """ + Whether to request for search suggestions on the _entityName virtualized field + """ + getSuggestions: Boolean } """ @@ -483,6 +488,11 @@ type SearchResults { Candidate facet aggregations used for search filtering """ facets: [FacetMetadata!] + + """ + Search suggestions based on the query provided for alternate query texts + """ + suggestions: [SearchSuggestion!] } """ @@ -665,6 +675,11 @@ type MatchedField { Value of the field that matched """ value: String! + + """ + Entity if the value is an urn + """ + entity: Entity } """ @@ -722,6 +737,31 @@ type AggregationMetadata { entity: Entity } +""" +A suggestion for an alternate search query given an original query compared to all +of the entity names in our search index. +""" +type SearchSuggestion { + """ + The suggested text based on the provided query text compared to + the entity name field in the search index. + """ + text: String! + + """ + The "edit distance" for this suggestion. The closer this number is to 1, the + closer the suggested text is to the original text. The closer it is to 0, the + further from the original text it is. + """ + score: Float + + """ + The number of entities that would match on the name field given the suggested text + """ + frequency: Int +} + + """ Input for performing an auto completion query against a single Metadata Entity """ diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/TestUtils.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/TestUtils.java index 0718cc5b01d7ea..272a93fa1989c9 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/TestUtils.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/TestUtils.java @@ -9,12 +9,24 @@ import com.linkedin.common.AuditStamp; import com.linkedin.common.urn.UrnUtils; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; +import com.linkedin.metadata.models.registry.ConfigEntityRegistry; +import com.linkedin.metadata.models.registry.EntityRegistry; import com.linkedin.mxe.MetadataChangeProposal; import org.mockito.Mockito; +import java.util.List; + public class TestUtils { + public static EntityService getMockEntityService() { + EntityRegistry registry = new ConfigEntityRegistry(TestUtils.class.getResourceAsStream("/test-entity-registry.yaml")); + EntityService mockEntityService = Mockito.mock(EntityService.class); + Mockito.when(mockEntityService.getEntityRegistry()).thenReturn(registry); + return mockEntityService; + } + public static QueryContext getMockAllowContext() { return getMockAllowContext("urn:li:corpuser:test"); } @@ -88,25 +100,47 @@ public static QueryContext getMockDenyContext(String actorUrn, AuthorizationRequ } public static void verifyIngestProposal(EntityService mockService, int numberOfInvocations, MetadataChangeProposal proposal) { + verifyIngestProposal(mockService, numberOfInvocations, List.of(proposal)); + } + + public static void verifyIngestProposal(EntityService mockService, int numberOfInvocations, List proposals) { + AspectsBatchImpl batch = AspectsBatchImpl.builder() + .mcps(proposals, mockService.getEntityRegistry()) + .build(); + Mockito.verify(mockService, Mockito.times(numberOfInvocations)).ingestProposal( + Mockito.eq(batch), + Mockito.any(AuditStamp.class), + Mockito.eq(false) + ); + } + + public static void verifySingleIngestProposal(EntityService mockService, int numberOfInvocations, MetadataChangeProposal proposal) { Mockito.verify(mockService, Mockito.times(numberOfInvocations)).ingestProposal( - Mockito.eq(proposal), - Mockito.any(AuditStamp.class), - Mockito.eq(false) + Mockito.eq(proposal), + Mockito.any(AuditStamp.class), + Mockito.eq(false) ); } public static void verifyIngestProposal(EntityService mockService, int numberOfInvocations) { Mockito.verify(mockService, Mockito.times(numberOfInvocations)).ingestProposal( - Mockito.any(MetadataChangeProposal.class), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.eq(false) ); } + public static void verifySingleIngestProposal(EntityService mockService, int numberOfInvocations) { + Mockito.verify(mockService, Mockito.times(numberOfInvocations)).ingestProposal( + Mockito.any(MetadataChangeProposal.class), + Mockito.any(AuditStamp.class), + Mockito.eq(false) + ); + } + public static void verifyNoIngestProposal(EntityService mockService) { Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), - Mockito.any(AuditStamp.class), Mockito.anyBoolean()); + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } private TestUtils() { } diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/assertion/DeleteAssertionResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/assertion/DeleteAssertionResolverTest.java index 42d2b864309edd..8afec0a8895776 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/assertion/DeleteAssertionResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/assertion/DeleteAssertionResolverTest.java @@ -31,7 +31,7 @@ public class DeleteAssertionResolverTest { public void testGetSuccess() throws Exception { EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ASSERTION_URN))).thenReturn(true); Mockito.when(mockService.getAspect( Urn.createFromString(TEST_ASSERTION_URN), @@ -78,7 +78,7 @@ public void testGetSuccess() throws Exception { public void testGetSuccessNoAssertionInfoFound() throws Exception { EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ASSERTION_URN))).thenReturn(true); Mockito.when(mockService.getAspect( Urn.createFromString(TEST_ASSERTION_URN), @@ -117,7 +117,7 @@ public void testGetSuccessAssertionAlreadyRemoved() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ASSERTION_URN))).thenReturn(false); DeleteAssertionResolver resolver = new DeleteAssertionResolver(mockClient, mockService); @@ -151,7 +151,7 @@ public void testGetSuccessAssertionAlreadyRemoved() throws Exception { public void testGetUnauthorized() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ASSERTION_URN))).thenReturn(true); Mockito.when(mockService.getAspect( Urn.createFromString(TEST_ASSERTION_URN), @@ -189,7 +189,7 @@ public void testGetEntityClientException() throws Exception { Mockito.any(), Mockito.any(Authentication.class)); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ASSERTION_URN))).thenReturn(true); DeleteAssertionResolver resolver = new DeleteAssertionResolver(mockClient, mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/delete/BatchUpdateSoftDeletedResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/delete/BatchUpdateSoftDeletedResolverTest.java index 7e549f201c2c79..bae6f27a854bc7 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/delete/BatchUpdateSoftDeletedResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/delete/BatchUpdateSoftDeletedResolverTest.java @@ -11,8 +11,11 @@ import com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetchingEnvironment; + +import java.util.List; import java.util.concurrent.CompletionException; import org.mockito.Mockito; import org.testng.annotations.Test; @@ -29,7 +32,7 @@ public class BatchUpdateSoftDeletedResolverTest { @Test public void testGetSuccessNoExistingStatus() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -61,20 +64,17 @@ public void testGetSuccessNoExistingStatus() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), STATUS_ASPECT_NAME, newStatus); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), STATUS_ASPECT_NAME, newStatus); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); } @Test public void testGetSuccessExistingStatus() throws Exception { final Status originalStatus = new Status().setRemoved(true); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -105,18 +105,15 @@ public void testGetSuccessExistingStatus() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), STATUS_ASPECT_NAME, newStatus); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), STATUS_ASPECT_NAME, newStatus); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); } @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -148,7 +145,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchUpdateSoftDeletedResolver resolver = new BatchUpdateSoftDeletedResolver(mockService); @@ -166,10 +163,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchUpdateSoftDeletedResolver resolver = new BatchUpdateSoftDeletedResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/BatchUpdateDeprecationResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/BatchUpdateDeprecationResolverTest.java index 634fd59a857a69..ce5a02bb573e18 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/BatchUpdateDeprecationResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/BatchUpdateDeprecationResolverTest.java @@ -12,8 +12,11 @@ import com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetchingEnvironment; + +import java.util.List; import java.util.concurrent.CompletionException; import org.mockito.Mockito; import org.testng.annotations.Test; @@ -30,7 +33,7 @@ public class BatchUpdateDeprecationResolverTest { @Test public void testGetSuccessNoExistingDeprecation() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -68,12 +71,10 @@ public void testGetSuccessNoExistingDeprecation() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), DEPRECATION_ASPECT_NAME, newDeprecation); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), DEPRECATION_ASPECT_NAME, newDeprecation); - verifyIngestProposal(mockService, 1, proposal2); + + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); } @Test @@ -83,7 +84,7 @@ public void testGetSuccessExistingDeprecation() throws Exception { .setNote("") .setActor(UrnUtils.getUrn("urn:li:corpuser:test")); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -120,18 +121,15 @@ public void testGetSuccessExistingDeprecation() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), DEPRECATION_ASPECT_NAME, newDeprecation); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), DEPRECATION_ASPECT_NAME, newDeprecation); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); } @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -164,7 +162,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchUpdateDeprecationResolver resolver = new BatchUpdateDeprecationResolver(mockService); @@ -183,10 +181,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchUpdateDeprecationResolver resolver = new BatchUpdateDeprecationResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/UpdateDeprecationResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/UpdateDeprecationResolverTest.java index cf11ecf8650851..5d30ae08d6dea2 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/UpdateDeprecationResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/deprecation/UpdateDeprecationResolverTest.java @@ -58,7 +58,7 @@ public void testGetSuccessNoExistingDeprecation() throws Exception { .setUrn(Urn.createFromString(TEST_ENTITY_URN)) .setAspects(new EnvelopedAspectMap(Collections.emptyMap())))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(true); UpdateDeprecationResolver resolver = new UpdateDeprecationResolver(mockClient, mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java index 9241661ccfc875..8cd3c71a21555b 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java @@ -14,9 +14,12 @@ import com.linkedin.events.metadata.ChangeType; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import com.linkedin.metadata.utils.GenericRecordUtils; import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetchingEnvironment; + +import java.util.List; import java.util.concurrent.CompletionException; import org.mockito.Mockito; import org.testng.annotations.Test; @@ -35,7 +38,7 @@ public class BatchSetDomainResolverTest { @Test public void testGetSuccessNoExistingDomains() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -74,13 +77,10 @@ public void testGetSuccessNoExistingDomains() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), DOMAINS_ASPECT_NAME, newDomains); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), DOMAINS_ASPECT_NAME, newDomains); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_DOMAIN_2_URN)) @@ -92,7 +92,7 @@ public void testGetSuccessExistingDomains() throws Exception { final Domains originalDomain = new Domains().setDomains(new UrnArray(ImmutableList.of( Urn.createFromString(TEST_DOMAIN_1_URN)))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -135,13 +135,10 @@ public void testGetSuccessExistingDomains() throws Exception { proposal1.setAspectName(Constants.DOMAINS_ASPECT_NAME); proposal1.setAspect(GenericRecordUtils.serializeAspect(newDomains)); proposal1.setChangeType(ChangeType.UPSERT); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), DOMAINS_ASPECT_NAME, newDomains); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_DOMAIN_2_URN)) @@ -153,7 +150,7 @@ public void testGetSuccessUnsetDomains() throws Exception { final Domains originalDomain = new Domains().setDomains(new UrnArray(ImmutableList.of( Urn.createFromString(TEST_DOMAIN_1_URN)))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -189,18 +186,15 @@ public void testGetSuccessUnsetDomains() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), DOMAINS_ASPECT_NAME, newDomains); - - verifyIngestProposal(mockService, 1, proposal1); - - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), + final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), DOMAINS_ASPECT_NAME, newDomains); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); } @Test public void testGetFailureDomainDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -228,7 +222,7 @@ public void testGetFailureDomainDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -262,7 +256,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); @@ -281,10 +275,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolverTest.java index 9343e5d7728262..560a3865ce9e1a 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/CreateDomainResolverTest.java @@ -6,49 +6,90 @@ import com.linkedin.common.urn.UrnUtils; import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.generated.CreateDomainInput; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.domain.DomainProperties; +import com.linkedin.entity.Aspect; +import com.linkedin.entity.EntityResponse; +import com.linkedin.entity.EnvelopedAspect; +import com.linkedin.entity.EnvelopedAspectMap; import com.linkedin.entity.client.EntityClient; import com.linkedin.events.metadata.ChangeType; import com.linkedin.metadata.Constants; import com.linkedin.metadata.key.DomainKey; +import com.linkedin.metadata.search.SearchEntity; +import com.linkedin.metadata.search.SearchEntityArray; +import com.linkedin.metadata.search.SearchResult; import com.linkedin.metadata.utils.GenericRecordUtils; import com.linkedin.metadata.entity.EntityService; import com.linkedin.mxe.MetadataChangeProposal; import com.linkedin.r2.RemoteInvocationException; import graphql.schema.DataFetchingEnvironment; + +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CompletionException; import org.mockito.Mockito; import org.testng.annotations.Test; import static com.linkedin.datahub.graphql.TestUtils.*; +import static com.linkedin.metadata.Constants.DOMAIN_PROPERTIES_ASPECT_NAME; import static org.testng.Assert.*; public class CreateDomainResolverTest { + private static final Urn TEST_DOMAIN_URN = Urn.createFromTuple("domain", "test-id"); + private static final Urn TEST_PARENT_DOMAIN_URN = Urn.createFromTuple("domain", "test-parent-id"); + private static final CreateDomainInput TEST_INPUT = new CreateDomainInput( "test-id", "test-name", - "test-description" + "test-description", + TEST_PARENT_DOMAIN_URN.toString() + ); + + private static final CreateDomainInput TEST_INPUT_NO_PARENT_DOMAIN = new CreateDomainInput( + "test-id", + "test-name", + "test-description", + null ); + private static final Urn TEST_ACTOR_URN = UrnUtils.getUrn("urn:li:corpuser:test"); - private static final String TEST_ENTITY_URN = "urn:li:dataset:(urn:li:dataPlatform:mysql,my-test,PROD)"; - private static final String TEST_TAG_1_URN = "urn:li:tag:test-id-1"; - private static final String TEST_TAG_2_URN = "urn:li:tag:test-id-2"; + @Test public void testGetSuccess() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); CreateDomainResolver resolver = new CreateDomainResolver(mockClient, mockService); + Mockito.when(mockClient.exists( + Mockito.eq(TEST_DOMAIN_URN), + Mockito.any(Authentication.class) + )).thenReturn(false); + + Mockito.when(mockClient.exists( + Mockito.eq(TEST_PARENT_DOMAIN_URN), + Mockito.any(Authentication.class) + )).thenReturn(true); + // Execute resolver QueryContext mockContext = getMockAllowContext(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); Mockito.when(mockEnv.getArgument(Mockito.eq("input"))).thenReturn(TEST_INPUT); Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + Mockito.when(mockClient.filter( + Mockito.eq(Constants.DOMAIN_ENTITY_NAME), + Mockito.eq(DomainUtils.buildNameAndParentDomainFilter(TEST_INPUT.getName(), TEST_PARENT_DOMAIN_URN)), + Mockito.eq(null), + Mockito.any(Integer.class), + Mockito.any(Integer.class), + Mockito.any(Authentication.class) + )).thenReturn(new SearchResult().setEntities(new SearchEntityArray())); + resolver.get(mockEnv).get(); final DomainKey key = new DomainKey(); @@ -60,6 +101,7 @@ public void testGetSuccess() throws Exception { props.setDescription("test-description"); props.setName("test-name"); props.setCreated(new AuditStamp().setActor(TEST_ACTOR_URN).setTime(0L)); + props.setParentDomain(TEST_PARENT_DOMAIN_URN); proposal.setAspectName(Constants.DOMAIN_PROPERTIES_ASPECT_NAME); proposal.setAspect(GenericRecordUtils.serializeAspect(props)); proposal.setChangeType(ChangeType.UPSERT); @@ -72,11 +114,138 @@ public void testGetSuccess() throws Exception { ); } + @Test + public void testGetSuccessNoParentDomain() throws Exception { + EntityClient mockClient = Mockito.mock(EntityClient.class); + EntityService mockService = Mockito.mock(EntityService.class); + CreateDomainResolver resolver = new CreateDomainResolver(mockClient, mockService); + + Mockito.when(mockClient.exists( + Mockito.eq(TEST_DOMAIN_URN), + Mockito.any(Authentication.class) + )).thenReturn(false); + + QueryContext mockContext = getMockAllowContext(); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument(Mockito.eq("input"))).thenReturn(TEST_INPUT_NO_PARENT_DOMAIN); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + Mockito.when(mockClient.filter( + Mockito.eq(Constants.DOMAIN_ENTITY_NAME), + Mockito.eq(DomainUtils.buildNameAndParentDomainFilter(TEST_INPUT.getName(), null)), + Mockito.eq(null), + Mockito.any(Integer.class), + Mockito.any(Integer.class), + Mockito.any(Authentication.class) + )).thenReturn(new SearchResult().setEntities(new SearchEntityArray())); + + resolver.get(mockEnv).get(); + + final DomainKey key = new DomainKey(); + key.setId("test-id"); + final MetadataChangeProposal proposal = new MetadataChangeProposal(); + proposal.setEntityKeyAspect(GenericRecordUtils.serializeAspect(key)); + proposal.setEntityType(Constants.DOMAIN_ENTITY_NAME); + DomainProperties props = new DomainProperties(); + props.setDescription("test-description"); + props.setName("test-name"); + props.setCreated(new AuditStamp().setActor(TEST_ACTOR_URN).setTime(0L)); + proposal.setAspectName(Constants.DOMAIN_PROPERTIES_ASPECT_NAME); + proposal.setAspect(GenericRecordUtils.serializeAspect(props)); + proposal.setChangeType(ChangeType.UPSERT); + + Mockito.verify(mockClient, Mockito.times(1)).ingestProposal( + Mockito.argThat(new CreateDomainProposalMatcher(proposal)), + Mockito.any(Authentication.class), + Mockito.eq(false) + ); + } + + @Test + public void testGetInvalidParent() throws Exception { + EntityClient mockClient = Mockito.mock(EntityClient.class); + EntityService mockService = Mockito.mock(EntityService.class); + CreateDomainResolver resolver = new CreateDomainResolver(mockClient, mockService); + + Mockito.when(mockClient.exists( + Mockito.eq(TEST_DOMAIN_URN), + Mockito.any(Authentication.class) + )).thenReturn(false); + + Mockito.when(mockClient.exists( + Mockito.eq(TEST_PARENT_DOMAIN_URN), + Mockito.any(Authentication.class) + )).thenReturn(false); + + QueryContext mockContext = getMockAllowContext(); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument(Mockito.eq("input"))).thenReturn(TEST_INPUT); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); + } + + @Test + public void testGetNameConflict() throws Exception { + EntityClient mockClient = Mockito.mock(EntityClient.class); + EntityService mockService = Mockito.mock(EntityService.class); + CreateDomainResolver resolver = new CreateDomainResolver(mockClient, mockService); + + Mockito.when(mockClient.exists( + Mockito.eq(TEST_DOMAIN_URN), + Mockito.any(Authentication.class) + )).thenReturn(false); + + Mockito.when(mockClient.exists( + Mockito.eq(TEST_PARENT_DOMAIN_URN), + Mockito.any(Authentication.class) + )).thenReturn(true); + + QueryContext mockContext = getMockAllowContext(); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument(Mockito.eq("input"))).thenReturn(TEST_INPUT); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + Mockito.when(mockClient.filter( + Mockito.eq(Constants.DOMAIN_ENTITY_NAME), + Mockito.eq(DomainUtils.buildNameAndParentDomainFilter(TEST_INPUT.getName(), TEST_PARENT_DOMAIN_URN)), + Mockito.eq(null), + Mockito.any(Integer.class), + Mockito.any(Integer.class), + Mockito.any(Authentication.class) + )).thenReturn(new SearchResult().setEntities( + new SearchEntityArray(new SearchEntity().setEntity(TEST_DOMAIN_URN)) + )); + + DomainProperties domainProperties = new DomainProperties(); + domainProperties.setDescription(TEST_INPUT.getDescription()); + domainProperties.setName(TEST_INPUT.getName()); + domainProperties.setCreated(new AuditStamp().setActor(TEST_ACTOR_URN).setTime(0L)); + domainProperties.setParentDomain(TEST_PARENT_DOMAIN_URN); + + EntityResponse entityResponse = new EntityResponse(); + EnvelopedAspectMap envelopedAspectMap = new EnvelopedAspectMap(); + envelopedAspectMap.put(DOMAIN_PROPERTIES_ASPECT_NAME, new EnvelopedAspect().setValue(new Aspect(domainProperties.data()))); + entityResponse.setAspects(envelopedAspectMap); + + Map entityResponseMap = new HashMap<>(); + entityResponseMap.put(TEST_DOMAIN_URN, entityResponse); + + Mockito.when(mockClient.batchGetV2( + Mockito.eq(Constants.DOMAIN_ENTITY_NAME), + Mockito.any(), + Mockito.any(), + Mockito.any(Authentication.class) + )).thenReturn(entityResponseMap); + + assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); + } + @Test public void testGetUnauthorized() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); CreateDomainResolver resolver = new CreateDomainResolver(mockClient, mockService); // Execute resolver @@ -95,7 +264,7 @@ public void testGetUnauthorized() throws Exception { public void testGetEntityClientException() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RemoteInvocationException.class).when(mockClient).ingestProposal( Mockito.any(), Mockito.any(Authentication.class), Mockito.eq(false)); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolverTest.java index 1c450b0e85424d..9bcdbe6d2a0e0a 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/DeleteDomainResolverTest.java @@ -4,6 +4,7 @@ import com.linkedin.common.urn.Urn; import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.entity.client.EntityClient; +import com.linkedin.metadata.search.SearchResult; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; import org.mockito.Mockito; @@ -28,6 +29,10 @@ public void testGetSuccess() throws Exception { Mockito.when(mockEnv.getArgument(Mockito.eq("urn"))).thenReturn(TEST_URN); Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + // Domain has 0 child domains + Mockito.when(mockClient.filter(Mockito.eq("domain"), Mockito.any(), Mockito.any(), Mockito.eq(0), Mockito.eq(1), Mockito.any())) + .thenReturn(new SearchResult().setNumEntities(0)); + assertTrue(resolver.get(mockEnv).get()); Mockito.verify(mockClient, Mockito.times(1)).deleteEntity( @@ -36,6 +41,28 @@ public void testGetSuccess() throws Exception { ); } + @Test + public void testDeleteWithChildDomains() throws Exception { + EntityClient mockClient = Mockito.mock(EntityClient.class); + DeleteDomainResolver resolver = new DeleteDomainResolver(mockClient); + + // Execute resolver + QueryContext mockContext = getMockAllowContext(); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument(Mockito.eq("urn"))).thenReturn(TEST_URN); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + // Domain has child domains + Mockito.when(mockClient.filter(Mockito.eq("domain"), Mockito.any(), Mockito.any(), Mockito.eq(0), Mockito.eq(1), Mockito.any())) + .thenReturn(new SearchResult().setNumEntities(1)); + + assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); + + Mockito.verify(mockClient, Mockito.times(0)).deleteEntity( + Mockito.any(), + Mockito.any(Authentication.class)); + } + @Test public void testGetUnauthorized() throws Exception { // Create resolver diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolverTest.java index c143f3480fcff1..bd8a8f98de4974 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/ListDomainsResolverTest.java @@ -5,6 +5,7 @@ import com.linkedin.common.urn.Urn; import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.generated.ListDomainsInput; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.query.SearchFlags; @@ -28,9 +29,14 @@ public class ListDomainsResolverTest { private static final Urn TEST_DOMAIN_URN = Urn.createFromTuple("domain", "test-id"); + private static final Urn TEST_PARENT_DOMAIN_URN = Urn.createFromTuple("domain", "test-parent-id"); private static final ListDomainsInput TEST_INPUT = new ListDomainsInput( - 0, 20, null + 0, 20, null, TEST_PARENT_DOMAIN_URN.toString() + ); + + private static final ListDomainsInput TEST_INPUT_NO_PARENT_DOMAIN = new ListDomainsInput( + 0, 20, null, null ); @Test @@ -41,7 +47,7 @@ public void testGetSuccess() throws Exception { Mockito.when(mockClient.search( Mockito.eq(Constants.DOMAIN_ENTITY_NAME), Mockito.eq(""), - Mockito.eq(null), + Mockito.eq(DomainUtils.buildParentDomainFilter(TEST_PARENT_DOMAIN_URN)), Mockito.eq(new SortCriterion().setField(DOMAIN_CREATED_TIME_INDEX_FIELD_NAME).setOrder(SortOrder.DESCENDING)), Mockito.eq(0), Mockito.eq(20), @@ -71,6 +77,44 @@ public void testGetSuccess() throws Exception { assertEquals(resolver.get(mockEnv).get().getDomains().get(0).getUrn(), TEST_DOMAIN_URN.toString()); } + @Test + public void testGetSuccessNoParentDomain() throws Exception { + // Create resolver + EntityClient mockClient = Mockito.mock(EntityClient.class); + + Mockito.when(mockClient.search( + Mockito.eq(Constants.DOMAIN_ENTITY_NAME), + Mockito.eq(""), + Mockito.eq(DomainUtils.buildParentDomainFilter(null)), + Mockito.eq(new SortCriterion().setField(DOMAIN_CREATED_TIME_INDEX_FIELD_NAME).setOrder(SortOrder.DESCENDING)), + Mockito.eq(0), + Mockito.eq(20), + Mockito.any(Authentication.class), + Mockito.eq(new SearchFlags().setFulltext(true)) + )).thenReturn( + new SearchResult() + .setFrom(0) + .setPageSize(1) + .setNumEntities(1) + .setEntities(new SearchEntityArray(ImmutableSet.of(new SearchEntity().setEntity(TEST_DOMAIN_URN)))) + ); + + ListDomainsResolver resolver = new ListDomainsResolver(mockClient); + + // Execute resolver + QueryContext mockContext = getMockAllowContext(); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument(Mockito.eq("input"))).thenReturn(TEST_INPUT_NO_PARENT_DOMAIN); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + // Data Assertions + assertEquals((int) resolver.get(mockEnv).get().getStart(), 0); + assertEquals((int) resolver.get(mockEnv).get().getCount(), 1); + assertEquals((int) resolver.get(mockEnv).get().getTotal(), 1); + assertEquals(resolver.get(mockEnv).get().getDomains().size(), 1); + assertEquals(resolver.get(mockEnv).get().getDomains().get(0).getUrn(), TEST_DOMAIN_URN.toString()); + } + @Test public void testGetUnauthorized() throws Exception { // Create resolver diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/MoveDomainResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/MoveDomainResolverTest.java new file mode 100644 index 00000000000000..4059c180b0eb03 --- /dev/null +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/MoveDomainResolverTest.java @@ -0,0 +1,140 @@ +package com.linkedin.datahub.graphql.resolvers.domain; + +import com.datahub.authentication.Authentication; +import com.linkedin.common.AuditStamp; +import com.linkedin.common.urn.CorpuserUrn; +import com.linkedin.common.urn.Urn; +import com.linkedin.datahub.graphql.QueryContext; +import com.linkedin.datahub.graphql.generated.MoveDomainInput; +import com.linkedin.datahub.graphql.resolvers.mutate.MoveDomainResolver; +import com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; +import com.linkedin.domain.DomainProperties; +import com.linkedin.entity.client.EntityClient; +import com.linkedin.metadata.Constants; +import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.search.SearchEntityArray; +import com.linkedin.metadata.search.SearchResult; +import com.linkedin.mxe.MetadataChangeProposal; +import graphql.schema.DataFetchingEnvironment; +import org.mockito.Mockito; +import org.testng.annotations.Test; + +import java.util.concurrent.CompletionException; + +import static com.linkedin.datahub.graphql.TestUtils.*; +import static com.linkedin.metadata.Constants.*; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.assertTrue; + +public class MoveDomainResolverTest { + + private static final String CONTAINER_URN = "urn:li:container:00005397daf94708a8822b8106cfd451"; + private static final String PARENT_DOMAIN_URN = "urn:li:domain:00005397daf94708a8822b8106cfd451"; + private static final String DOMAIN_URN = "urn:li:domain:11115397daf94708a8822b8106cfd451"; + private static final MoveDomainInput INPUT = new MoveDomainInput(PARENT_DOMAIN_URN, DOMAIN_URN); + private static final MoveDomainInput INVALID_INPUT = new MoveDomainInput(CONTAINER_URN, DOMAIN_URN); + private static final CorpuserUrn TEST_ACTOR_URN = new CorpuserUrn("test"); + + private MetadataChangeProposal setupTests(DataFetchingEnvironment mockEnv, EntityService mockService, EntityClient mockClient) throws Exception { + QueryContext mockContext = getMockAllowContext(); + Mockito.when(mockContext.getAuthentication()).thenReturn(Mockito.mock(Authentication.class)); + Mockito.when(mockContext.getActorUrn()).thenReturn(TEST_ACTOR_URN.toString()); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + final String name = "test name"; + Mockito.when(mockService.getAspect( + Urn.createFromString(DOMAIN_URN), + Constants.DOMAIN_PROPERTIES_ASPECT_NAME, + 0)) + .thenReturn(new DomainProperties().setName(name)); + + Mockito.when(mockClient.filter( + Mockito.eq(Constants.DOMAIN_ENTITY_NAME), + Mockito.eq(DomainUtils.buildNameAndParentDomainFilter(name, Urn.createFromString(PARENT_DOMAIN_URN))), + Mockito.eq(null), + Mockito.any(Integer.class), + Mockito.any(Integer.class), + Mockito.any(Authentication.class) + )).thenReturn(new SearchResult().setEntities(new SearchEntityArray())); + + DomainProperties properties = new DomainProperties(); + properties.setName(name); + properties.setParentDomain(Urn.createFromString(PARENT_DOMAIN_URN)); + return MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(DOMAIN_URN), + DOMAIN_PROPERTIES_ASPECT_NAME, properties); + } + + @Test + public void testGetSuccess() throws Exception { + EntityService mockService = Mockito.mock(EntityService.class); + EntityClient mockClient = Mockito.mock(EntityClient.class); + Mockito.when(mockService.exists(Urn.createFromString(PARENT_DOMAIN_URN))).thenReturn(true); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument("input")).thenReturn(INPUT); + + MoveDomainResolver resolver = new MoveDomainResolver(mockService, mockClient); + setupTests(mockEnv, mockService, mockClient); + + assertTrue(resolver.get(mockEnv).get()); + Mockito.verify(mockService, Mockito.times(1)).ingestProposal( + Mockito.any(MetadataChangeProposal.class), + Mockito.any(AuditStamp.class), + Mockito.eq(false) + ); + } + + @Test + public void testGetFailureEntityDoesNotExist() throws Exception { + EntityService mockService = Mockito.mock(EntityService.class); + EntityClient mockClient = Mockito.mock(EntityClient.class); + Mockito.when(mockService.exists(Urn.createFromString(PARENT_DOMAIN_URN))).thenReturn(true); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument("input")).thenReturn(INPUT); + + QueryContext mockContext = getMockAllowContext(); + Mockito.when(mockContext.getAuthentication()).thenReturn(Mockito.mock(Authentication.class)); + Mockito.when(mockContext.getActorUrn()).thenReturn(TEST_ACTOR_URN.toString()); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + Mockito.when(mockService.getAspect( + Urn.createFromString(DOMAIN_URN), + DOMAIN_PROPERTIES_ASPECT_NAME, + 0)) + .thenReturn(null); + + MoveDomainResolver resolver = new MoveDomainResolver(mockService, mockClient); + assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); + verifyNoIngestProposal(mockService); + } + + @Test + public void testGetFailureParentDoesNotExist() throws Exception { + EntityService mockService = Mockito.mock(EntityService.class); + EntityClient mockClient = Mockito.mock(EntityClient.class); + Mockito.when(mockService.exists(Urn.createFromString(PARENT_DOMAIN_URN))).thenReturn(false); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument("input")).thenReturn(INPUT); + + MoveDomainResolver resolver = new MoveDomainResolver(mockService, mockClient); + setupTests(mockEnv, mockService, mockClient); + + assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); + verifyNoIngestProposal(mockService); + } + + @Test + public void testGetFailureParentIsNotDomain() throws Exception { + EntityService mockService = Mockito.mock(EntityService.class); + EntityClient mockClient = Mockito.mock(EntityClient.class); + Mockito.when(mockService.exists(Urn.createFromString(PARENT_DOMAIN_URN))).thenReturn(true); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getArgument("input")).thenReturn(INVALID_INPUT); + + MoveDomainResolver resolver = new MoveDomainResolver(mockService, mockClient); + setupTests(mockEnv, mockService, mockClient); + + assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); + verifyNoIngestProposal(mockService); + } +} diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/ParentDomainsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/ParentDomainsResolverTest.java new file mode 100644 index 00000000000000..7bd7c3afac001c --- /dev/null +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/ParentDomainsResolverTest.java @@ -0,0 +1,95 @@ +package com.linkedin.datahub.graphql.resolvers.domain; + +import com.datahub.authentication.Authentication; +import com.linkedin.common.urn.Urn; +import com.linkedin.datahub.graphql.QueryContext; +import com.linkedin.datahub.graphql.generated.Domain; +import com.linkedin.datahub.graphql.generated.EntityType; +import com.linkedin.datahub.graphql.generated.ParentDomainsResult; +import com.linkedin.domain.DomainProperties; +import com.linkedin.entity.Aspect; +import com.linkedin.entity.EntityResponse; +import com.linkedin.entity.EnvelopedAspect; +import com.linkedin.entity.EnvelopedAspectMap; +import com.linkedin.entity.client.EntityClient; +import graphql.schema.DataFetchingEnvironment; +import org.mockito.Mockito; +import org.testng.annotations.Test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static com.linkedin.metadata.Constants.*; +import static org.testng.Assert.assertEquals; + +public class ParentDomainsResolverTest { + @Test + public void testGetSuccessForDomain() throws Exception { + EntityClient mockClient = Mockito.mock(EntityClient.class); + QueryContext mockContext = Mockito.mock(QueryContext.class); + Mockito.when(mockContext.getAuthentication()).thenReturn(Mockito.mock(Authentication.class)); + DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); + Mockito.when(mockEnv.getContext()).thenReturn(mockContext); + + Urn domainUrn = Urn.createFromString("urn:li:domain:00005397daf94708a8822b8106cfd451"); + Domain domainEntity = new Domain(); + domainEntity.setUrn(domainUrn.toString()); + domainEntity.setType(EntityType.DOMAIN); + Mockito.when(mockEnv.getSource()).thenReturn(domainEntity); + + final DomainProperties parentDomain1 = new DomainProperties().setParentDomain(Urn.createFromString( + "urn:li:domain:11115397daf94708a8822b8106cfd451") + ).setName("test def"); + final DomainProperties parentDomain2 = new DomainProperties().setParentDomain(Urn.createFromString( + "urn:li:domain:22225397daf94708a8822b8106cfd451") + ).setName("test def 2"); + + Map domainAspects = new HashMap<>(); + domainAspects.put(DOMAIN_PROPERTIES_ASPECT_NAME, new EnvelopedAspect().setValue(new Aspect(parentDomain1.data()))); + + Map parentDomain1Aspects = new HashMap<>(); + parentDomain1Aspects.put(DOMAIN_PROPERTIES_ASPECT_NAME, new EnvelopedAspect().setValue(new Aspect( + new DomainProperties().setName("domain parent 1").setParentDomain(parentDomain2.getParentDomain()).data() + ))); + + Map parentDomain2Aspects = new HashMap<>(); + parentDomain2Aspects.put(DOMAIN_PROPERTIES_ASPECT_NAME, new EnvelopedAspect().setValue(new Aspect( + new DomainProperties().setName("domain parent 2").data() + ))); + + Mockito.when(mockClient.getV2( + Mockito.eq(domainUrn.getEntityType()), + Mockito.eq(domainUrn), + Mockito.eq(Collections.singleton(DOMAIN_PROPERTIES_ASPECT_NAME)), + Mockito.any(Authentication.class) + )).thenReturn(new EntityResponse().setAspects(new EnvelopedAspectMap(domainAspects))); + + Mockito.when(mockClient.getV2( + Mockito.eq(parentDomain1.getParentDomain().getEntityType()), + Mockito.eq(parentDomain1.getParentDomain()), + Mockito.eq(Collections.singleton(DOMAIN_PROPERTIES_ASPECT_NAME)), + Mockito.any(Authentication.class) + )).thenReturn(new EntityResponse().setAspects(new EnvelopedAspectMap(parentDomain1Aspects))); + + Mockito.when(mockClient.getV2( + Mockito.eq(parentDomain2.getParentDomain().getEntityType()), + Mockito.eq(parentDomain2.getParentDomain()), + Mockito.eq(Collections.singleton(DOMAIN_PROPERTIES_ASPECT_NAME)), + Mockito.any(Authentication.class) + )).thenReturn(new EntityResponse().setAspects(new EnvelopedAspectMap(parentDomain2Aspects))); + + ParentDomainsResolver resolver = new ParentDomainsResolver(mockClient); + ParentDomainsResult result = resolver.get(mockEnv).get(); + + Mockito.verify(mockClient, Mockito.times(3)).getV2( + Mockito.any(), + Mockito.any(), + Mockito.any(), + Mockito.any() + ); + assertEquals(result.getCount(), 2); + assertEquals(result.getDomains().get(0).getUrn(), parentDomain1.getParentDomain().toString()); + assertEquals(result.getDomains().get(1).getUrn(), parentDomain2.getParentDomain().toString()); + } +} \ No newline at end of file diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolverTest.java index 73d1f699dfd807..92fb26288aa1dc 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolverTest.java @@ -54,7 +54,7 @@ public void testGetSuccessNoExistingDomains() throws Exception { .setUrn(Urn.createFromString(TEST_ENTITY_URN)) .setAspects(new EnvelopedAspectMap(Collections.emptyMap())))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(true); Mockito.when(mockService.exists(Urn.createFromString(TEST_NEW_DOMAIN_URN))).thenReturn(true); @@ -110,7 +110,7 @@ public void testGetSuccessExistingDomains() throws Exception { new EnvelopedAspect().setValue(new Aspect(originalDomains.data())) ))))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(true); Mockito.when(mockService.exists(Urn.createFromString(TEST_NEW_DOMAIN_URN))).thenReturn(true); @@ -160,7 +160,7 @@ public void testGetFailureDomainDoesNotExist() throws Exception { .setUrn(Urn.createFromString(TEST_ENTITY_URN)) .setAspects(new EnvelopedAspectMap(Collections.emptyMap())))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(true); Mockito.when(mockService.exists(Urn.createFromString(TEST_NEW_DOMAIN_URN))).thenReturn(false); @@ -196,7 +196,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { .setUrn(Urn.createFromString(TEST_ENTITY_URN)) .setAspects(new EnvelopedAspectMap(Collections.emptyMap())))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(false); Mockito.when(mockService.exists(Urn.createFromString(TEST_NEW_DOMAIN_URN))).thenReturn(true); @@ -219,7 +219,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { public void testGetUnauthorized() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); SetDomainResolver resolver = new SetDomainResolver(mockClient, mockService); // Execute resolver diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolverTest.java index 18b2b9a2747e2c..decda39943dde3 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolverTest.java @@ -53,7 +53,7 @@ public void testGetSuccessNoExistingDomains() throws Exception { .setUrn(Urn.createFromString(TEST_ENTITY_URN)) .setAspects(new EnvelopedAspectMap(Collections.emptyMap())))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(true); UnsetDomainResolver resolver = new UnsetDomainResolver(mockClient, mockService); @@ -104,7 +104,7 @@ public void testGetSuccessExistingDomains() throws Exception { new EnvelopedAspect().setValue(new Aspect(originalDomains.data())) ))))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(true); UnsetDomainResolver resolver = new UnsetDomainResolver(mockClient, mockService); @@ -148,7 +148,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { .setUrn(Urn.createFromString(TEST_ENTITY_URN)) .setAspects(new EnvelopedAspectMap(Collections.emptyMap())))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(false); UnsetDomainResolver resolver = new UnsetDomainResolver(mockClient, mockService); @@ -169,7 +169,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { public void testGetUnauthorized() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); UnsetDomainResolver resolver = new UnsetDomainResolver(mockClient, mockService); // Execute resolver diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/embed/UpdateEmbedResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/embed/UpdateEmbedResolverTest.java index 17f7a1968fdf60..f1d44fcb472556 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/embed/UpdateEmbedResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/embed/UpdateEmbedResolverTest.java @@ -15,6 +15,7 @@ import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import com.linkedin.mxe.MetadataChangeProposal; import com.linkedin.r2.RemoteInvocationException; import graphql.schema.DataFetchingEnvironment; @@ -41,7 +42,7 @@ public class UpdateEmbedResolverTest { @Test public void testGetSuccessNoExistingEmbed() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)), @@ -64,11 +65,7 @@ public void testGetSuccessNoExistingEmbed() throws Exception { final MetadataChangeProposal proposal = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN), EMBED_ASPECT_NAME, newEmbed); - Mockito.verify(mockService, Mockito.times(1)).ingestProposal( - Mockito.eq(proposal), - Mockito.any(AuditStamp.class), - Mockito.eq(false) - ); + verifySingleIngestProposal(mockService, 1, proposal);; Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)) @@ -80,7 +77,7 @@ public void testGetSuccessExistingEmbed() throws Exception { Embed originalEmbed = new Embed().setRenderUrl("https://otherurl.com"); // Create resolver - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)), @@ -103,11 +100,7 @@ public void testGetSuccessExistingEmbed() throws Exception { final MetadataChangeProposal proposal = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN), EMBED_ASPECT_NAME, newEmbed); - Mockito.verify(mockService, Mockito.times(1)).ingestProposal( - Mockito.eq(proposal), - Mockito.any(AuditStamp.class), - Mockito.eq(false) - ); + verifySingleIngestProposal(mockService, 1, proposal); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)) @@ -130,7 +123,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { .setUrn(Urn.createFromString(TEST_ENTITY_URN)) .setAspects(new EnvelopedAspectMap(Collections.emptyMap())))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(false); UpdateEmbedResolver resolver = new UpdateEmbedResolver(mockService); @@ -144,7 +137,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.eq(false) );; @@ -153,7 +146,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { // Create resolver - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); UpdateEmbedResolver resolver = new UpdateEmbedResolver(mockService); // Execute resolver @@ -164,7 +157,7 @@ public void testGetUnauthorized() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.eq(false) ); @@ -173,7 +166,7 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RemoteInvocationException.class).when(mockClient).ingestProposal( Mockito.any(), Mockito.any(Authentication.class)); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolverTest.java index 6bbf4f47975607..26c13186c4a817 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolverTest.java @@ -27,7 +27,7 @@ public class AddRelatedTermsResolverTest { private static final String DATASET_URN = "urn:li:dataset:(test,test,test)"; private EntityService setUpService() { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), Mockito.eq(Constants.GLOSSARY_RELATED_TERM_ASPECT_NAME), @@ -56,7 +56,7 @@ public void testGetSuccessIsRelatedNonExistent() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1); + verifySingleIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)) ); @@ -88,7 +88,7 @@ public void testGetSuccessHasRelatedNonExistent() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1); + verifySingleIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)) ); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryNodeResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryNodeResolverTest.java index 392ddf6ac4c747..3b47514d87181b 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryNodeResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryNodeResolverTest.java @@ -15,6 +15,7 @@ import org.testng.annotations.Test; import static com.linkedin.datahub.graphql.TestUtils.getMockAllowContext; +import static com.linkedin.datahub.graphql.TestUtils.getMockEntityService; import static com.linkedin.metadata.Constants.*; @@ -69,7 +70,7 @@ private MetadataChangeProposal setupTest( @Test public void testGetSuccess() throws Exception { EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); final MetadataChangeProposal proposal = setupTest(mockEnv, TEST_INPUT, "test-description", parentNodeUrn); @@ -86,7 +87,7 @@ public void testGetSuccess() throws Exception { @Test public void testGetSuccessNoDescription() throws Exception { EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); final MetadataChangeProposal proposal = setupTest(mockEnv, TEST_INPUT_NO_DESCRIPTION, "", parentNodeUrn); @@ -103,7 +104,7 @@ public void testGetSuccessNoDescription() throws Exception { @Test public void testGetSuccessNoParentNode() throws Exception { EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); final MetadataChangeProposal proposal = setupTest(mockEnv, TEST_INPUT_NO_PARENT_NODE, "test-description", null); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryTermResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryTermResolverTest.java index e4f32133b4b515..2dbe637d160572 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryTermResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/CreateGlossaryTermResolverTest.java @@ -29,6 +29,7 @@ import java.util.concurrent.CompletionException; import static com.linkedin.datahub.graphql.TestUtils.getMockAllowContext; +import static com.linkedin.datahub.graphql.TestUtils.getMockEntityService; import static org.testng.Assert.assertThrows; import static com.linkedin.metadata.Constants.*; @@ -86,7 +87,7 @@ private MetadataChangeProposal setupTest( @Test public void testGetSuccess() throws Exception { EntityClient mockClient = initMockClient(); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); final MetadataChangeProposal proposal = setupTest(mockEnv, TEST_INPUT, "test-description", parentNodeUrn); @@ -103,7 +104,7 @@ public void testGetSuccess() throws Exception { @Test public void testGetSuccessNoDescription() throws Exception { EntityClient mockClient = initMockClient(); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); final MetadataChangeProposal proposal = setupTest(mockEnv, TEST_INPUT_NO_DESCRIPTION, "", parentNodeUrn); @@ -120,7 +121,7 @@ public void testGetSuccessNoDescription() throws Exception { @Test public void testGetSuccessNoParentNode() throws Exception { EntityClient mockClient = initMockClient(); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); final MetadataChangeProposal proposal = setupTest(mockEnv, TEST_INPUT_NO_PARENT_NODE, "test-description", null); @@ -166,7 +167,7 @@ public void testGetFailureExistingTermSameName() throws Exception { ) ).thenReturn(result); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); CreateGlossaryEntityInput input = new CreateGlossaryEntityInput( diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolverTest.java index df24c23e89ae6d..94f0d0b7a11434 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolverTest.java @@ -13,6 +13,7 @@ import java.util.concurrent.CompletionException; import static com.linkedin.datahub.graphql.TestUtils.getMockAllowContext; +import static com.linkedin.datahub.graphql.TestUtils.getMockEntityService; import static org.testng.Assert.assertThrows; import static org.testng.Assert.assertTrue; @@ -23,7 +24,7 @@ public class DeleteGlossaryEntityResolverTest { @Test public void testGetSuccess() throws Exception { EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_TERM_URN))).thenReturn(true); @@ -48,7 +49,7 @@ public void testGetEntityClientException() throws Exception { Mockito.any(), Mockito.any(Authentication.class)); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_TERM_URN))).thenReturn(true); DeleteGlossaryEntityResolver resolver = new DeleteGlossaryEntityResolver(mockClient, mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolverTest.java index dd54d7f9835c1d..3906d1188cb172 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolverTest.java @@ -34,7 +34,7 @@ public void testGetSuccessIsA() throws Exception { GlossaryTermUrn term2Urn = GlossaryTermUrn.createFromString(TEST_TERM_2_URN); final GlossaryRelatedTerms relatedTerms = new GlossaryRelatedTerms(); relatedTerms.setIsRelatedTerms(new GlossaryTermUrnArray(Arrays.asList(term1Urn, term2Urn))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), Mockito.eq(Constants.GLOSSARY_RELATED_TERM_ASPECT_NAME), @@ -54,7 +54,7 @@ public void testGetSuccessIsA() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1); + verifySingleIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)) ); @@ -66,7 +66,7 @@ public void testGetSuccessHasA() throws Exception { GlossaryTermUrn term2Urn = GlossaryTermUrn.createFromString(TEST_TERM_2_URN); final GlossaryRelatedTerms relatedTerms = new GlossaryRelatedTerms(); relatedTerms.setHasRelatedTerms(new GlossaryTermUrnArray(Arrays.asList(term1Urn, term2Urn))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), Mockito.eq(Constants.GLOSSARY_RELATED_TERM_ASPECT_NAME), @@ -86,7 +86,7 @@ public void testGetSuccessHasA() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1); + verifySingleIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_ENTITY_URN)) ); @@ -94,7 +94,7 @@ public void testGetSuccessHasA() throws Exception { @Test public void testFailAspectDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), Mockito.eq(Constants.GLOSSARY_RELATED_TERM_ASPECT_NAME), @@ -123,7 +123,7 @@ public void testFailNoPermissions() throws Exception { GlossaryTermUrn term2Urn = GlossaryTermUrn.createFromString(TEST_TERM_2_URN); final GlossaryRelatedTerms relatedTerms = new GlossaryRelatedTerms(); relatedTerms.setIsRelatedTerms(new GlossaryTermUrnArray(Arrays.asList(term1Urn, term2Urn))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), Mockito.eq(Constants.GLOSSARY_RELATED_TERM_ASPECT_NAME), diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateNameResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateNameResolverTest.java index 36f909bd7ebe54..eee9cfbae8fcb2 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateNameResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateNameResolverTest.java @@ -8,12 +8,15 @@ import com.linkedin.datahub.graphql.generated.UpdateNameInput; import com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils; import com.linkedin.datahub.graphql.resolvers.mutate.UpdateNameResolver; +import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.domain.DomainProperties; import com.linkedin.entity.client.EntityClient; import com.linkedin.glossary.GlossaryNodeInfo; import com.linkedin.glossary.GlossaryTermInfo; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.search.SearchEntityArray; +import com.linkedin.metadata.search.SearchResult; import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetchingEnvironment; import org.mockito.Mockito; @@ -58,7 +61,7 @@ private MetadataChangeProposal setupTests(DataFetchingEnvironment mockEnv, Entit @Test public void testGetSuccess() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(TERM_URN))).thenReturn(true); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); @@ -68,12 +71,12 @@ public void testGetSuccess() throws Exception { final MetadataChangeProposal proposal = setupTests(mockEnv, mockService); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1, proposal); + verifySingleIngestProposal(mockService, 1, proposal); } @Test public void testGetSuccessForNode() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(NODE_URN))).thenReturn(true); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); @@ -98,12 +101,12 @@ public void testGetSuccessForNode() throws Exception { UpdateNameResolver resolver = new UpdateNameResolver(mockService, mockClient); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1, proposal); + verifySingleIngestProposal(mockService, 1, proposal); } @Test public void testGetSuccessForDomain() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(DOMAIN_URN))).thenReturn(true); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); @@ -121,6 +124,15 @@ public void testGetSuccessForDomain() throws Exception { 0)) .thenReturn(new DomainProperties().setName(name)); + Mockito.when(mockClient.filter( + Mockito.eq(Constants.DOMAIN_ENTITY_NAME), + Mockito.eq(DomainUtils.buildNameAndParentDomainFilter(INPUT_FOR_DOMAIN.getName(), null)), + Mockito.eq(null), + Mockito.any(Integer.class), + Mockito.any(Integer.class), + Mockito.any(Authentication.class) + )).thenReturn(new SearchResult().setEntities(new SearchEntityArray())); + DomainProperties properties = new DomainProperties(); properties.setName(NEW_NAME); final MetadataChangeProposal proposal = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(DOMAIN_URN), @@ -129,12 +141,12 @@ public void testGetSuccessForDomain() throws Exception { UpdateNameResolver resolver = new UpdateNameResolver(mockService, mockClient); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1, proposal); + verifySingleIngestProposal(mockService, 1, proposal); } @Test public void testGetFailureEntityDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(TERM_URN))).thenReturn(false); DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateParentNodeResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateParentNodeResolverTest.java index 43c6113d194a59..a78c28890fecf3 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateParentNodeResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/glossary/UpdateParentNodeResolverTest.java @@ -58,7 +58,7 @@ private MetadataChangeProposal setupTests(DataFetchingEnvironment mockEnv, Entit @Test public void testGetSuccess() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(TERM_URN))).thenReturn(true); Mockito.when(mockService.exists(GlossaryNodeUrn.createFromString(PARENT_NODE_URN))).thenReturn(true); @@ -69,12 +69,12 @@ public void testGetSuccess() throws Exception { final MetadataChangeProposal proposal = setupTests(mockEnv, mockService); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1, proposal); + verifySingleIngestProposal(mockService, 1, proposal); } @Test public void testGetSuccessForNode() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(NODE_URN))).thenReturn(true); Mockito.when(mockService.exists(GlossaryNodeUrn.createFromString(PARENT_NODE_URN))).thenReturn(true); @@ -102,12 +102,12 @@ public void testGetSuccessForNode() throws Exception { UpdateParentNodeResolver resolver = new UpdateParentNodeResolver(mockService, mockClient); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 1, proposal); + verifySingleIngestProposal(mockService, 1, proposal); } @Test public void testGetFailureEntityDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(TERM_URN))).thenReturn(false); Mockito.when(mockService.exists(GlossaryNodeUrn.createFromString(PARENT_NODE_URN))).thenReturn(true); @@ -123,7 +123,7 @@ public void testGetFailureEntityDoesNotExist() throws Exception { @Test public void testGetFailureNodeDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(TERM_URN))).thenReturn(true); Mockito.when(mockService.exists(GlossaryNodeUrn.createFromString(PARENT_NODE_URN))).thenReturn(false); @@ -139,7 +139,7 @@ public void testGetFailureNodeDoesNotExist() throws Exception { @Test public void testGetFailureParentIsNotNode() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockService.exists(Urn.createFromString(TERM_URN))).thenReturn(true); Mockito.when(mockService.exists(GlossaryNodeUrn.createFromString(PARENT_NODE_URN))).thenReturn(true); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateUserSettingResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateUserSettingResolverTest.java index c7f1e16a0ea610..9bd44e9ab09065 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateUserSettingResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateUserSettingResolverTest.java @@ -21,7 +21,7 @@ public class UpdateUserSettingResolverTest { private static final String TEST_USER_URN = "urn:li:corpuser:test"; @Test public void testWriteCorpUserSettings() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_USER_URN))).thenReturn(true); UpdateUserSettingResolver resolver = new UpdateUserSettingResolver(mockService); @@ -40,6 +40,6 @@ public void testWriteCorpUserSettings() throws Exception { final MetadataChangeProposal proposal = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_USER_URN), CORP_USER_SETTINGS_ASPECT_NAME, newSettings); - verifyIngestProposal(mockService, 1, proposal); + verifySingleIngestProposal(mockService, 1, proposal); } } diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java index 9bdb3c1db2b0ac..efc0c5dfcf36d8 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java @@ -13,6 +13,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; import org.mockito.Mockito; @@ -30,7 +31,7 @@ public class AddOwnersResolverTest { @Test public void testGetSuccessNoExistingOwners() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -75,7 +76,7 @@ public void testGetSuccessNoExistingOwners() throws Exception { @Test public void testGetSuccessExistingOwners() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -120,7 +121,7 @@ public void testGetSuccessExistingOwners() throws Exception { @Test public void testGetFailureOwnerDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -148,7 +149,7 @@ public void testGetFailureOwnerDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -176,7 +177,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); AddOwnersResolver resolver = new AddOwnersResolver(mockService); @@ -195,10 +196,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); AddOwnersResolver resolver = new AddOwnersResolver(Mockito.mock(EntityService.class)); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java index e38eb9eb677c27..79fc62742f4442 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java @@ -17,6 +17,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; import org.mockito.Mockito; @@ -35,7 +36,7 @@ public class BatchAddOwnersResolverTest { @Test public void testGetSuccessNoExistingOwners() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -82,7 +83,7 @@ public void testGetSuccessNoExistingOwners() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_OWNER_URN_1)) @@ -98,7 +99,7 @@ public void testGetSuccessExistingOwners() throws Exception { final Ownership originalOwnership = new Ownership().setOwners(new OwnerArray(ImmutableList.of( new Owner().setOwner(Urn.createFromString(TEST_OWNER_URN_1)).setType(OwnershipType.TECHNICAL_OWNER) ))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -150,7 +151,7 @@ public void testGetSuccessExistingOwners() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_OWNER_URN_1)) @@ -163,7 +164,7 @@ public void testGetSuccessExistingOwners() throws Exception { @Test public void testGetFailureOwnerDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -202,7 +203,7 @@ public void testGetFailureOwnerDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -247,7 +248,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); @@ -277,10 +278,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java index 0884d442ea5311..9dc2ec81278069 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java @@ -14,6 +14,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.BatchRemoveOwnersResolver; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; import org.mockito.Mockito; @@ -32,7 +33,7 @@ public class BatchRemoveOwnersResolverTest { @Test public void testGetSuccessNoExistingOwners() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -66,12 +67,12 @@ public void testGetSuccessNoExistingOwners() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); } @Test public void testGetSuccessExistingOwners() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); final Ownership oldOwners1 = new Ownership().setOwners(new OwnerArray(ImmutableList.of( new Owner().setOwner(Urn.createFromString(TEST_OWNER_URN_1)).setType(OwnershipType.TECHNICAL_OWNER) @@ -112,12 +113,12 @@ public void testGetSuccessExistingOwners() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); } @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -152,7 +153,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService); @@ -172,10 +173,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/AddTagsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/AddTagsResolverTest.java index 06d9df32788471..268d6a6bc4268d 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/AddTagsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/AddTagsResolverTest.java @@ -13,6 +13,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.AddTagsResolver; import com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; @@ -32,7 +33,7 @@ public class AddTagsResolverTest { @Test public void testGetSuccessNoExistingTags() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -82,7 +83,7 @@ public void testGetSuccessExistingTags() throws Exception { new TagAssociation().setTag(TagUrn.createFromString(TEST_TAG_1_URN)))) ); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -128,7 +129,7 @@ public void testGetSuccessExistingTags() throws Exception { @Test public void testGetFailureTagDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -156,7 +157,7 @@ public void testGetFailureTagDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -184,7 +185,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); AddTagsResolver resolver = new AddTagsResolver(mockService); @@ -203,10 +204,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.eq(false)); AddTagsResolver resolver = new AddTagsResolver(Mockito.mock(EntityService.class)); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchAddTagsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchAddTagsResolverTest.java index d47e6164fe221c..651b89359c83fa 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchAddTagsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchAddTagsResolverTest.java @@ -15,8 +15,11 @@ import com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetchingEnvironment; + +import java.util.List; import java.util.concurrent.CompletionException; import org.mockito.Mockito; import org.testng.annotations.Test; @@ -35,7 +38,7 @@ public class BatchAddTagsResolverTest { @Test public void testGetSuccessNoExistingTags() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -78,13 +81,10 @@ public void testGetSuccessNoExistingTags() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), GLOBAL_TAGS_ASPECT_NAME, newTags); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), GLOBAL_TAGS_ASPECT_NAME, newTags); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_TAG_1_URN)) @@ -101,7 +101,7 @@ public void testGetSuccessExistingTags() throws Exception { new TagAssociation().setTag(TagUrn.createFromString(TEST_TAG_1_URN)))) ); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -143,13 +143,10 @@ public void testGetSuccessExistingTags() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), GLOBAL_TAGS_ASPECT_NAME, newTags); - - verifyIngestProposal(mockService, 1, proposal1); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), GLOBAL_TAGS_ASPECT_NAME, newTags); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_TAG_1_URN)) @@ -162,7 +159,7 @@ public void testGetSuccessExistingTags() throws Exception { @Test public void testGetFailureTagDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -188,13 +185,13 @@ public void testGetFailureTagDoesNotExist() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -227,13 +224,13 @@ public void testGetFailureResourceDoesNotExist() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchAddTagsResolver resolver = new BatchAddTagsResolver(mockService); @@ -251,16 +248,16 @@ public void testGetUnauthorized() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchAddTagsResolver resolver = new BatchAddTagsResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchRemoveTagsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchRemoveTagsResolverTest.java index 44160cfbe1273c..f302540eba9048 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchRemoveTagsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/BatchRemoveTagsResolverTest.java @@ -16,10 +16,12 @@ import com.linkedin.events.metadata.ChangeType; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import com.linkedin.metadata.utils.GenericRecordUtils; import com.linkedin.mxe.MetadataChangeProposal; import graphql.schema.DataFetchingEnvironment; import java.util.Collections; +import java.util.List; import java.util.concurrent.CompletionException; import org.mockito.Mockito; import org.testng.annotations.Test; @@ -38,7 +40,7 @@ public class BatchRemoveTagsResolverTest { @Test public void testGetSuccessNoExistingTags() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -76,12 +78,6 @@ public void testGetSuccessNoExistingTags() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), GLOBAL_TAGS_ASPECT_NAME, emptyTags); - - Mockito.verify(mockService, Mockito.times(1)).ingestProposal( - Mockito.eq(proposal1), - Mockito.any(AuditStamp.class), Mockito.eq(false) - ); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), GLOBAL_TAGS_ASPECT_NAME, emptyTags); proposal2.setEntityUrn(Urn.createFromString(TEST_ENTITY_URN_2)); @@ -90,12 +86,12 @@ public void testGetSuccessNoExistingTags() throws Exception { proposal2.setAspect(GenericRecordUtils.serializeAspect(emptyTags)); proposal2.setChangeType(ChangeType.UPSERT); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); } @Test public void testGetSuccessExistingTags() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); final GlobalTags oldTags1 = new GlobalTags().setTags(new TagAssociationArray(ImmutableList.of( new TagAssociation().setTag(TagUrn.createFromString(TEST_TAG_1_URN)), @@ -143,21 +139,15 @@ public void testGetSuccessExistingTags() throws Exception { final MetadataChangeProposal proposal1 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_1), GLOBAL_TAGS_ASPECT_NAME, emptyTags); - - Mockito.verify(mockService, Mockito.times(1)).ingestProposal( - Mockito.eq(proposal1), - Mockito.any(AuditStamp.class), Mockito.eq(false) - ); - final MetadataChangeProposal proposal2 = MutationUtils.buildMetadataChangeProposalWithUrn(Urn.createFromString(TEST_ENTITY_URN_2), GLOBAL_TAGS_ASPECT_NAME, emptyTags); - verifyIngestProposal(mockService, 1, proposal2); + verifyIngestProposal(mockService, 1, List.of(proposal1, proposal2)); } @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -190,13 +180,13 @@ public void testGetFailureResourceDoesNotExist() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchRemoveTagsResolver resolver = new BatchRemoveTagsResolver(mockService); @@ -214,16 +204,16 @@ public void testGetUnauthorized() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchRemoveTagsResolver resolver = new BatchRemoveTagsResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/CreateTagResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/CreateTagResolverTest.java index d294f806d1af7f..f801daf4f2a3f1 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/CreateTagResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/CreateTagResolverTest.java @@ -31,7 +31,7 @@ public class CreateTagResolverTest { @Test public void testGetSuccess() throws Exception { // Create resolver - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when(mockClient.ingestProposal(Mockito.any(MetadataChangeProposal.class), Mockito.any(Authentication.class))) .thenReturn(String.format("urn:li:tag:%s", TEST_INPUT.getId())); @@ -64,7 +64,7 @@ public void testGetSuccess() throws Exception { @Test public void testGetUnauthorized() throws Exception { // Create resolver - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); CreateTagResolver resolver = new CreateTagResolver(mockClient, mockService); @@ -83,7 +83,7 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { // Create resolver - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.doThrow(RuntimeException.class).when(mockClient).ingestProposal( Mockito.any(), diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/SetTagColorResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/SetTagColorResolverTest.java index da474ca3e0e561..b5bbf0775a8bae 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/SetTagColorResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/tag/SetTagColorResolverTest.java @@ -37,7 +37,7 @@ public class SetTagColorResolverTest { public void testGetSuccessExistingProperties() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); // Test setting the domain final TagProperties oldTagProperties = new TagProperties().setName("Test Tag"); @@ -78,7 +78,7 @@ public void testGetSuccessExistingProperties() throws Exception { public void testGetFailureNoExistingProperties() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); // Test setting the domain Mockito.when(mockService.getAspect( @@ -127,7 +127,7 @@ public void testGetFailureTagDoesNotExist() throws Exception { Constants.TAG_PROPERTIES_ASPECT_NAME, oldTagPropertiesAspect))))); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.exists(Urn.createFromString(TEST_ENTITY_URN))).thenReturn(false); SetTagColorResolver resolver = new SetTagColorResolver(mockClient, mockService); @@ -148,7 +148,7 @@ public void testGetFailureTagDoesNotExist() throws Exception { public void testGetUnauthorized() throws Exception { // Create resolver EntityClient mockClient = Mockito.mock(EntityClient.class); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); SetTagColorResolver resolver = new SetTagColorResolver(mockClient, mockService); // Execute resolver diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/AddTermsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/AddTermsResolverTest.java index c9ec92001f89bc..213d21fd35dc1e 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/AddTermsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/AddTermsResolverTest.java @@ -13,7 +13,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.AddTermsResolver; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; -import com.linkedin.mxe.MetadataChangeProposal; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; import org.mockito.Mockito; @@ -31,7 +31,7 @@ public class AddTermsResolverTest { @Test public void testGetSuccessNoExistingTerms() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -58,7 +58,7 @@ public void testGetSuccessNoExistingTerms() throws Exception { // Unable to easily validate exact payload due to the injected timestamp Mockito.verify(mockService, Mockito.times(1)).ingestProposal( - Mockito.any(MetadataChangeProposal.class), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.eq(false) ); @@ -77,7 +77,7 @@ public void testGetSuccessExistingTerms() throws Exception { new GlossaryTermAssociation().setUrn(GlossaryTermUrn.createFromString(TEST_TERM_1_URN)))) ); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -104,7 +104,7 @@ public void testGetSuccessExistingTerms() throws Exception { // Unable to easily validate exact payload due to the injected timestamp Mockito.verify(mockService, Mockito.times(1)).ingestProposal( - Mockito.any(MetadataChangeProposal.class), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.eq(false) ); @@ -119,7 +119,7 @@ public void testGetSuccessExistingTerms() throws Exception { @Test public void testGetFailureTermDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -143,13 +143,13 @@ public void testGetFailureTermDoesNotExist() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN)), @@ -173,13 +173,13 @@ public void testGetFailureResourceDoesNotExist() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); AddTermsResolver resolver = new AddTermsResolver(mockService); @@ -194,16 +194,16 @@ public void testGetUnauthorized() throws Exception { assertThrows(CompletionException.class, () -> resolver.get(mockEnv).join()); Mockito.verify(mockService, Mockito.times(0)).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); } @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); AddTermsResolver resolver = new AddTermsResolver(Mockito.mock(EntityService.class)); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchAddTermsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchAddTermsResolverTest.java index dfe1394635c4ed..8887bb452b478c 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchAddTermsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchAddTermsResolverTest.java @@ -14,6 +14,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.BatchAddTermsResolver; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; import org.mockito.Mockito; @@ -32,7 +33,7 @@ public class BatchAddTermsResolverTest { @Test public void testGetSuccessNoExistingTerms() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -66,7 +67,7 @@ public void testGetSuccessNoExistingTerms() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_GLOSSARY_TERM_1_URN)) @@ -83,7 +84,7 @@ public void testGetSuccessExistingTerms() throws Exception { new GlossaryTermAssociation().setUrn(GlossaryTermUrn.createFromString(TEST_GLOSSARY_TERM_1_URN)))) ); - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -118,7 +119,7 @@ public void testGetSuccessExistingTerms() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); Mockito.verify(mockService, Mockito.times(1)).exists( Mockito.eq(Urn.createFromString(TEST_GLOSSARY_TERM_1_URN)) @@ -131,7 +132,7 @@ public void testGetSuccessExistingTerms() throws Exception { @Test public void testGetFailureTagDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -160,7 +161,7 @@ public void testGetFailureTagDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -196,7 +197,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchAddTermsResolver resolver = new BatchAddTermsResolver(mockService); @@ -217,10 +218,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchAddTermsResolver resolver = new BatchAddTermsResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchRemoveTermsResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchRemoveTermsResolverTest.java index dcc8659c1baf3b..995a4acb8a4676 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchRemoveTermsResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/term/BatchRemoveTermsResolverTest.java @@ -14,6 +14,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.BatchRemoveTermsResolver; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; +import com.linkedin.metadata.entity.ebean.transactions.AspectsBatchImpl; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; import org.mockito.Mockito; @@ -32,7 +33,7 @@ public class BatchRemoveTermsResolverTest { @Test public void testGetSuccessNoExistingTerms() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -66,12 +67,12 @@ public void testGetSuccessNoExistingTerms() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); } @Test public void testGetSuccessExistingTerms() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); final GlossaryTerms oldTerms1 = new GlossaryTerms().setTerms(new GlossaryTermAssociationArray(ImmutableList.of( new GlossaryTermAssociation().setUrn(GlossaryTermUrn.createFromString(TEST_TERM_1_URN)), @@ -115,12 +116,12 @@ public void testGetSuccessExistingTerms() throws Exception { Mockito.when(mockEnv.getContext()).thenReturn(mockContext); assertTrue(resolver.get(mockEnv).get()); - verifyIngestProposal(mockService, 2); + verifyIngestProposal(mockService, 1); } @Test public void testGetFailureResourceDoesNotExist() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.when(mockService.getAspect( Mockito.eq(UrnUtils.getUrn(TEST_ENTITY_URN_1)), @@ -157,7 +158,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); BatchRemoveTermsResolver resolver = new BatchRemoveTermsResolver(mockService); @@ -179,10 +180,10 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { - EntityService mockService = Mockito.mock(EntityService.class); + EntityService mockService = getMockEntityService(); Mockito.doThrow(RuntimeException.class).when(mockService).ingestProposal( - Mockito.any(), + Mockito.any(AspectsBatchImpl.class), Mockito.any(AuditStamp.class), Mockito.anyBoolean()); BatchRemoveTermsResolver resolver = new BatchRemoveTermsResolver(mockService); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/utils/SystemMetadataUtilsTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/utils/SystemMetadataUtilsTest.java index dc9b0d97812ae4..adbc6808b5ab9e 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/utils/SystemMetadataUtilsTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/utils/SystemMetadataUtilsTest.java @@ -1,9 +1,11 @@ package com.linkedin.datahub.graphql.utils; +import com.linkedin.datahub.graphql.types.common.mappers.util.RunInfo; import com.linkedin.datahub.graphql.types.common.mappers.util.SystemMetadataUtils; import com.linkedin.entity.EnvelopedAspect; import com.linkedin.entity.EnvelopedAspectMap; import com.linkedin.mxe.SystemMetadata; +import java.util.List; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -17,7 +19,7 @@ public class SystemMetadataUtilsTest { private final Long distantLastObserved = 1657226036292L; @Test - public void testGetLastIngested() { + public void testGetLastIngestedTime() { EnvelopedAspectMap aspectMap = new EnvelopedAspectMap(); aspectMap.put("default-run-id", new EnvelopedAspect().setSystemMetadata( new SystemMetadata().setRunId(DEFAULT_RUN_ID).setLastObserved(recentLastObserved) @@ -29,12 +31,49 @@ public void testGetLastIngested() { new SystemMetadata().setRunId("real-id-2").setLastObserved(distantLastObserved) )); - Long lastObserved = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastObserved = SystemMetadataUtils.getLastIngestedTime(aspectMap); assertEquals(lastObserved, mediumLastObserved); } @Test - public void testGetLastIngestedAllDefaultRunIds() { + public void testGetLastIngestedRunId() { + EnvelopedAspectMap aspectMap = new EnvelopedAspectMap(); + aspectMap.put("default-run-id", new EnvelopedAspect().setSystemMetadata( + new SystemMetadata().setRunId(DEFAULT_RUN_ID).setLastObserved(recentLastObserved) + )); + aspectMap.put("real-run-id", new EnvelopedAspect().setSystemMetadata( + new SystemMetadata().setRunId("real-id-1").setLastObserved(mediumLastObserved) + )); + aspectMap.put("real-run-id2", new EnvelopedAspect().setSystemMetadata( + new SystemMetadata().setRunId("real-id-2").setLastObserved(distantLastObserved) + )); + + String lastRunId = SystemMetadataUtils.getLastIngestedRunId(aspectMap); + assertEquals(lastRunId, "real-id-1"); + } + + @Test + public void testGetLastIngestedRuns() { + EnvelopedAspectMap aspectMap = new EnvelopedAspectMap(); + aspectMap.put("default-run-id", new EnvelopedAspect().setSystemMetadata( + new SystemMetadata().setRunId(DEFAULT_RUN_ID).setLastObserved(recentLastObserved) + )); + aspectMap.put("real-run-id", new EnvelopedAspect().setSystemMetadata( + new SystemMetadata().setRunId("real-id-1").setLastObserved(mediumLastObserved) + )); + aspectMap.put("real-run-id2", new EnvelopedAspect().setSystemMetadata( + new SystemMetadata().setRunId("real-id-2").setLastObserved(distantLastObserved) + )); + + List runs = SystemMetadataUtils.getLastIngestionRuns(aspectMap); + + assertEquals(runs.size(), 2); + assertEquals(runs.get(0), new RunInfo("real-id-1", mediumLastObserved)); + assertEquals(runs.get(1), new RunInfo("real-id-2", distantLastObserved)); + } + + @Test + public void testGetLastIngestedTimeAllDefaultRunIds() { EnvelopedAspectMap aspectMap = new EnvelopedAspectMap(); aspectMap.put("default-run-id", new EnvelopedAspect().setSystemMetadata( new SystemMetadata().setRunId(DEFAULT_RUN_ID).setLastObserved(recentLastObserved) @@ -46,7 +85,7 @@ public void testGetLastIngestedAllDefaultRunIds() { new SystemMetadata().setRunId(DEFAULT_RUN_ID).setLastObserved(distantLastObserved) )); - Long lastObserved = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastObserved = SystemMetadataUtils.getLastIngestedTime(aspectMap); assertNull(lastObserved, null); } @@ -54,7 +93,7 @@ public void testGetLastIngestedAllDefaultRunIds() { public void testGetLastIngestedNoAspects() { EnvelopedAspectMap aspectMap = new EnvelopedAspectMap(); - Long lastObserved = SystemMetadataUtils.getLastIngested(aspectMap); + Long lastObserved = SystemMetadataUtils.getLastIngestedTime(aspectMap); assertNull(lastObserved, null); } } diff --git a/datahub-graphql-core/src/test/resources/test-entity-registry.yaml b/datahub-graphql-core/src/test/resources/test-entity-registry.yaml new file mode 100644 index 00000000000000..d694ae53ac42f7 --- /dev/null +++ b/datahub-graphql-core/src/test/resources/test-entity-registry.yaml @@ -0,0 +1,295 @@ +entities: +- name: dataPlatform + category: core + keyAspect: dataPlatformKey + aspects: + - dataPlatformInfo +- name: dataset + doc: Datasets represent logical or physical data assets stored or represented in various data platforms. Tables, Views, Streams are all instances of datasets. + category: core + keyAspect: datasetKey + aspects: + - viewProperties + - subTypes + - datasetProfile + - datasetUsageStatistics + - operation + - domains + - status + - container + - deprecation + - testResults + - siblings + - embed + - ownership + - glossaryTerms + - globalTags +- name: dataHubPolicy + doc: DataHub Policies represent access policies granted to users or groups on metadata operations like edit, view etc. + category: internal + keyAspect: dataHubPolicyKey + aspects: + - dataHubPolicyInfo +- name: dataJob + keyAspect: dataJobKey + aspects: + - datahubIngestionRunSummary + - datahubIngestionCheckpoint + - domains + - deprecation + - versionInfo +- name: dataFlow + category: core + keyAspect: dataFlowKey + aspects: + - domains + - deprecation + - versionInfo +- name: dataProcessInstance + doc: DataProcessInstance represents an instance of a datajob/jobflow run + keyAspect: dataProcessInstanceKey + aspects: + - dataProcessInstanceInput + - dataProcessInstanceOutput + - dataProcessInstanceProperties + - dataProcessInstanceRelationships + - dataProcessInstanceRunEvent +- name: chart + keyAspect: chartKey + aspects: + - domains + - container + - deprecation + - chartUsageStatistics + - embed +- name: dashboard + keyAspect: dashboardKey + aspects: + - domains + - container + - deprecation + - dashboardUsageStatistics + - subTypes + - embed +- name: notebook + doc: Notebook represents a combination of query, text, chart and etc. This is in BETA version + keyAspect: notebookKey + aspects: + - notebookInfo + - notebookContent + - editableNotebookProperties + - ownership + - status + - globalTags + - glossaryTerms + - browsePaths + - institutionalMemory + - domains + - subTypes + - dataPlatformInstance +- name: corpuser + doc: CorpUser represents an identity of a person (or an account) in the enterprise. + keyAspect: corpUserKey + aspects: + - corpUserInfo + - corpUserEditableInfo + - corpUserStatus + - groupMembership + - globalTags + - status + - corpUserCredentials + - nativeGroupMembership + - corpUserSettings + - origin + - roleMembership +- name: corpGroup + doc: CorpGroup represents an identity of a group of users in the enterprise. + keyAspect: corpGroupKey + aspects: + - corpGroupInfo + - corpGroupEditableInfo + - globalTags + - ownership + - status + - origin +- name: domain + doc: A data domain within an organization. + keyAspect: domainKey + aspects: + - domainProperties + - institutionalMemory + - ownership +- name: container + doc: A container of related data assets. + keyAspect: containerKey + aspects: + - containerProperties + - editableContainerProperties + - dataPlatformInstance + - subTypes + - ownership + - container + - globalTags + - glossaryTerms + - institutionalMemory + - browsePaths # unclear if this will be used + - status + - domains +- name: tag + keyAspect: tagKey + aspects: + - tagProperties + - ownership + - deprecation +- name: glossaryTerm + keyAspect: glossaryTermKey + aspects: + - glossaryTermInfo + - institutionalMemory + - ownership + - deprecation + - domains +- name: glossaryNode + keyAspect: glossaryNodeKey + aspects: + - glossaryNodeInfo + - institutionalMemory + - ownership + - status +- name: dataHubIngestionSource + category: internal + keyAspect: dataHubIngestionSourceKey + aspects: + - dataHubIngestionSourceInfo +- name: dataHubSecret + category: internal + keyAspect: dataHubSecretKey + aspects: + - dataHubSecretValue +- name: dataHubExecutionRequest + category: internal + keyAspect: dataHubExecutionRequestKey + aspects: + - dataHubExecutionRequestInput + - dataHubExecutionRequestSignal + - dataHubExecutionRequestResult +- name: assertion + doc: Assertion represents a data quality rule applied on one or more dataset. + category: core + keyAspect: assertionKey + aspects: + - assertionInfo + - dataPlatformInstance + - assertionRunEvent + - status +- name: dataHubRetention + category: internal + keyAspect: dataHubRetentionKey + aspects: + - dataHubRetentionConfig +- name: dataPlatformInstance + category: internal + keyAspect: dataPlatformInstanceKey + aspects: + - dataPlatformInstanceProperties + - ownership + - globalTags + - institutionalMemory + - deprecation + - status +- name: mlModel + category: core + keyAspect: mlModelKey + aspects: + - glossaryTerms + - editableMlModelProperties + - domains +- name: mlModelGroup + category: core + keyAspect: mlModelGroupKey + aspects: + - glossaryTerms + - editableMlModelGroupProperties + - domains +- name: mlFeatureTable + category: core + keyAspect: mlFeatureTableKey + aspects: + - glossaryTerms + - editableMlFeatureTableProperties + - domains +- name: mlFeature + category: core + keyAspect: mlFeatureKey + aspects: + - glossaryTerms + - editableMlFeatureProperties + - domains +- name: mlPrimaryKey + category: core + keyAspect: mlPrimaryKeyKey + aspects: + - glossaryTerms + - editableMlPrimaryKeyProperties + - domains +- name: telemetry + category: internal + keyAspect: telemetryKey + aspects: + - telemetryClientId +- name: dataHubAccessToken + category: internal + keyAspect: dataHubAccessTokenKey + aspects: + - dataHubAccessTokenInfo +- name: test + doc: A DataHub test + category: core + keyAspect: testKey + aspects: + - testInfo +- name: dataHubUpgrade + category: internal + keyAspect: dataHubUpgradeKey + aspects: + - dataHubUpgradeRequest + - dataHubUpgradeResult +- name: inviteToken + category: core + keyAspect: inviteTokenKey + aspects: + - inviteToken +- name: globalSettings + doc: Global settings for an the platform + category: internal + keyAspect: globalSettingsKey + aspects: + - globalSettingsInfo +- name: dataHubRole + category: core + keyAspect: dataHubRoleKey + aspects: + - dataHubRoleInfo +- name: post + category: core + keyAspect: postKey + aspects: + - postInfo +- name: dataHubStepState + category: core + keyAspect: dataHubStepStateKey + aspects: + - dataHubStepStateProperties +- name: dataHubView + category: core + keyAspect: dataHubViewKey + aspects: + - dataHubViewInfo +- name: ownershipType + doc: Ownership Type represents a user-created ownership category for a person or group who is responsible for an asset. + category: core + keyAspect: ownershipTypeKey + aspects: + - ownershipTypeInfo + - status +events: diff --git a/datahub-upgrade/build.gradle b/datahub-upgrade/build.gradle index 78d9f6a09948d2..5d0edf3ee8427c 100644 --- a/datahub-upgrade/build.gradle +++ b/datahub-upgrade/build.gradle @@ -12,14 +12,15 @@ ext { } dependencies { - compile project(':metadata-io') - compile project(':metadata-service:factories') - compile project(':metadata-service:restli-client') - compile project(':metadata-service:configuration') + implementation project(':metadata-io') + implementation project(':metadata-service:factories') + implementation project(':metadata-service:restli-client') + implementation project(':metadata-service:configuration') + implementation project(':metadata-dao-impl:kafka-producer') implementation externalDependency.charle - compile externalDependency.javaxInject - compile(externalDependency.hadoopClient) { + implementation externalDependency.javaxInject + implementation(externalDependency.hadoopClient) { exclude group: 'net.minidev', module: 'json-smart' exclude group: 'com.nimbusds', module: 'nimbus-jose-jwt' exclude group: "org.apache.htrace", module: "htrace-core4" @@ -52,18 +53,18 @@ dependencies { implementation externalDependency.slf4jApi compileOnly externalDependency.lombok - compile externalDependency.picocli - compile externalDependency.parquet + implementation externalDependency.picocli + implementation externalDependency.parquet implementation externalDependency.protobuf - compile externalDependency.springBeans - compile externalDependency.springBootAutoconfigure - compile externalDependency.springCore - compile externalDependency.springKafka + implementation externalDependency.springBeans + implementation externalDependency.springBootAutoconfigure + implementation externalDependency.springCore + implementation externalDependency.springKafka - runtime externalDependency.logbackClassic - runtime externalDependency.mariadbConnector - runtime externalDependency.mysqlConnector - runtime externalDependency.postgresql + runtimeOnly externalDependency.logbackClassic + runtimeOnly externalDependency.mariadbConnector + runtimeOnly externalDependency.mysqlConnector + runtimeOnly externalDependency.postgresql implementation externalDependency.awsMskIamAuth @@ -71,9 +72,9 @@ dependencies { annotationProcessor externalDependency.picocli testImplementation externalDependency.springBootTest - testCompile externalDependency.mockito - testCompile externalDependency.testng - testRuntime externalDependency.logbackClassic + testImplementation externalDependency.mockito + testImplementation externalDependency.testng + testRuntimeOnly externalDependency.logbackClassic } bootJar { @@ -99,7 +100,7 @@ docker { load(true) push(false) } -tasks.getByName("docker").dependsOn([bootJar]) +tasks.getByPath(":datahub-upgrade:docker").dependsOn([bootJar]) task cleanLocalDockerImages { doLast { diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeCleanupConfig.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeCleanupConfig.java index 23ce409c746d0a..0fb8b0eb6e20f2 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeCleanupConfig.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeCleanupConfig.java @@ -3,7 +3,7 @@ import com.linkedin.datahub.upgrade.nocodecleanup.NoCodeCleanupUpgrade; import com.linkedin.metadata.graph.GraphService; import com.linkedin.metadata.utils.elasticsearch.IndexConvention; -import io.ebean.EbeanServer; +import io.ebean.Database; import javax.annotation.Nonnull; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Autowired; @@ -25,7 +25,7 @@ public class NoCodeCleanupConfig { @DependsOn({"ebeanServer", "graphService", "elasticSearchRestHighLevelClient", INDEX_CONVENTION_BEAN}) @Nonnull public NoCodeCleanupUpgrade createInstance() { - final EbeanServer ebeanServer = applicationContext.getBean(EbeanServer.class); + final Database ebeanServer = applicationContext.getBean(Database.class); final GraphService graphClient = applicationContext.getBean(GraphService.class); final RestHighLevelClient searchClient = applicationContext.getBean(RestHighLevelClient.class); final IndexConvention indexConvention = applicationContext.getBean(IndexConvention.class); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeUpgradeConfig.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeUpgradeConfig.java index 39b3daa73b78f7..30175c6fa78c88 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeUpgradeConfig.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/NoCodeUpgradeConfig.java @@ -5,7 +5,7 @@ import com.linkedin.entity.client.RestliEntityClient; import com.linkedin.metadata.entity.EntityService; import com.linkedin.metadata.models.registry.EntityRegistry; -import io.ebean.EbeanServer; +import io.ebean.Database; import javax.annotation.Nonnull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -24,7 +24,7 @@ public class NoCodeUpgradeConfig { @DependsOn({"ebeanServer", "entityService", "systemAuthentication", "restliEntityClient", "entityRegistry"}) @Nonnull public NoCodeUpgrade createInstance() { - final EbeanServer ebeanServer = applicationContext.getBean(EbeanServer.class); + final Database ebeanServer = applicationContext.getBean(Database.class); final EntityService entityService = applicationContext.getBean(EntityService.class); final Authentication systemAuthentication = applicationContext.getBean(Authentication.class); final RestliEntityClient entityClient = applicationContext.getBean(RestliEntityClient.class); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreBackupConfig.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreBackupConfig.java index ebff7f4b899adf..9b0fcf279abf54 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreBackupConfig.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreBackupConfig.java @@ -7,7 +7,7 @@ import com.linkedin.metadata.graph.GraphService; import com.linkedin.metadata.models.registry.EntityRegistry; import com.linkedin.metadata.search.EntitySearchService; -import io.ebean.EbeanServer; +import io.ebean.Database; import javax.annotation.Nonnull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -26,7 +26,7 @@ public class RestoreBackupConfig { "searchService", "entityRegistry"}) @Nonnull public RestoreBackup createInstance() { - final EbeanServer ebeanServer = applicationContext.getBean(EbeanServer.class); + final Database ebeanServer = applicationContext.getBean(Database.class); final EntityService entityService = applicationContext.getBean(EntityService.class); final Authentication systemAuthentication = applicationContext.getBean(Authentication.class); final RestliEntityClient entityClient = applicationContext.getBean(RestliEntityClient.class); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreIndicesConfig.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreIndicesConfig.java index ee907005168b8b..663cad4a4bff63 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreIndicesConfig.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/config/RestoreIndicesConfig.java @@ -5,7 +5,7 @@ import com.linkedin.metadata.graph.GraphService; import com.linkedin.metadata.models.registry.EntityRegistry; import com.linkedin.metadata.search.EntitySearchService; -import io.ebean.EbeanServer; +import io.ebean.Database; import javax.annotation.Nonnull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -23,7 +23,7 @@ public class RestoreIndicesConfig { @DependsOn({"ebeanServer", "entityService", "searchService", "graphService", "entityRegistry"}) @Nonnull public RestoreIndices createInstance() { - final EbeanServer ebeanServer = applicationContext.getBean(EbeanServer.class); + final Database ebeanServer = applicationContext.getBean(Database.class); final EntityService entityService = applicationContext.getBean(EntityService.class); final EntitySearchService entitySearchService = applicationContext.getBean(EntitySearchService.class); final GraphService graphService = applicationContext.getBean(GraphService.class); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java index 3b78e95a7b751d..7ed7169bf20bcc 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/CreateAspectTableStep.java @@ -4,7 +4,7 @@ import com.linkedin.datahub.upgrade.UpgradeContext; import com.linkedin.datahub.upgrade.UpgradeStep; import com.linkedin.datahub.upgrade.UpgradeStepResult; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.function.Function; public class CreateAspectTableStep implements UpgradeStep { @@ -17,9 +17,9 @@ enum DbType { MARIA } - private final EbeanServer _server; + private final Database _server; - public CreateAspectTableStep(final EbeanServer server) { + public CreateAspectTableStep(final Database server) { _server = server; } diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/DataMigrationStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/DataMigrationStep.java index 6553bb80bb1fac..1b5770a11ff62c 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/DataMigrationStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/DataMigrationStep.java @@ -17,10 +17,12 @@ import com.linkedin.metadata.entity.ebean.EbeanAspectV1; import com.linkedin.metadata.entity.ebean.EbeanAspectV2; import com.linkedin.metadata.models.EntitySpec; -import io.ebean.EbeanServer; +import com.linkedin.util.Pair; +import io.ebean.Database; import io.ebean.PagedList; import java.net.URISyntaxException; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -35,13 +37,13 @@ public class DataMigrationStep implements UpgradeStep { private static final String BROWSE_PATHS_ASPECT_NAME = PegasusUtils.getAspectNameFromSchema(new BrowsePaths().schema()); - private final EbeanServer _server; + private final Database _server; private final EntityService _entityService; private final EntityRegistry _entityRegistry; private final Set urnsWithBrowsePath = new HashSet<>(); public DataMigrationStep( - final EbeanServer server, + final Database server, final EntityService entityService, final EntityRegistry entityRegistry) { _server = server; @@ -132,15 +134,11 @@ public Function executable() { // 6. Write the row back using the EntityService boolean emitMae = oldAspect.getKey().getVersion() == 0L; - _entityService.updateAspect( + _entityService.ingestAspects( urn, - entityName, - newAspectName, - aspectSpec, - aspectRecord, + List.of(Pair.of(newAspectName, aspectRecord)), toAuditStamp(oldAspect), - oldAspect.getKey().getVersion(), - emitMae + null ); // 7. If necessary, emit a browse path aspect. @@ -154,7 +152,7 @@ public Function executable() { browsePathsStamp.setActor(Urn.createFromString(Constants.SYSTEM_ACTOR)); browsePathsStamp.setTime(System.currentTimeMillis()); - _entityService.ingestAspect(urn, BROWSE_PATHS_ASPECT_NAME, browsePaths, browsePathsStamp, null); + _entityService.ingestAspects(urn, List.of(Pair.of(BROWSE_PATHS_ASPECT_NAME, browsePaths)), browsePathsStamp, null); urnsWithBrowsePath.add(urn); } catch (URISyntaxException e) { diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/NoCodeUpgrade.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/NoCodeUpgrade.java index c12ff201faf229..ee4a3bc504e77f 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/NoCodeUpgrade.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/NoCodeUpgrade.java @@ -10,7 +10,7 @@ import com.linkedin.entity.client.RestliEntityClient; import com.linkedin.metadata.entity.EntityService; import com.linkedin.metadata.models.registry.EntityRegistry; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -25,9 +25,9 @@ public class NoCodeUpgrade implements Upgrade { private final List _steps; private final List _cleanupSteps; - // Upgrade requires the EbeanServer. + // Upgrade requires the Database. public NoCodeUpgrade( - final EbeanServer server, + final Database server, final EntityService entityService, final EntityRegistry entityRegistry, final Authentication systemAuthentication, @@ -60,7 +60,7 @@ private List buildCleanupSteps() { } private List buildUpgradeSteps( - final EbeanServer server, + final Database server, final EntityService entityService, final EntityRegistry entityRegistry, final Authentication systemAuthentication, diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/RemoveAspectV2TableStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/RemoveAspectV2TableStep.java index 440884470463d2..cf8e848762f143 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/RemoveAspectV2TableStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/RemoveAspectV2TableStep.java @@ -4,7 +4,7 @@ import com.linkedin.datahub.upgrade.UpgradeStep; import com.linkedin.datahub.upgrade.UpgradeStepResult; import com.linkedin.datahub.upgrade.impl.DefaultUpgradeStepResult; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.function.Function; @@ -13,9 +13,9 @@ */ public class RemoveAspectV2TableStep implements UpgradeStep { - private final EbeanServer _server; + private final Database _server; - public RemoveAspectV2TableStep(final EbeanServer server) { + public RemoveAspectV2TableStep(final Database server) { _server = server; } @@ -28,7 +28,7 @@ public String id() { public Function executable() { return (context) -> { context.report().addLine("Cleanup requested. Dropping metadata_aspect_v2"); - _server.execute(_server.createSqlUpdate("DROP TABLE IF EXISTS metadata_aspect_v2")); + _server.execute(_server.sqlUpdate("DROP TABLE IF EXISTS metadata_aspect_v2")); return new DefaultUpgradeStepResult(id(), UpgradeStepResult.Result.SUCCEEDED); }; } diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/UpgradeQualificationStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/UpgradeQualificationStep.java index ec05f210f0132e..0fe9afa8cc6f83 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/UpgradeQualificationStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocode/UpgradeQualificationStep.java @@ -5,14 +5,14 @@ import com.linkedin.datahub.upgrade.UpgradeStep; import com.linkedin.datahub.upgrade.UpgradeStepResult; import com.linkedin.metadata.entity.ebean.AspectStorageValidationUtil; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.function.Function; public class UpgradeQualificationStep implements UpgradeStep { - private final EbeanServer _server; + private final Database _server; - UpgradeQualificationStep(EbeanServer server) { + UpgradeQualificationStep(Database server) { _server = server; } @@ -52,7 +52,7 @@ public Function executable() { } // Check whether the upgrade is needed - private boolean isQualified(EbeanServer server, UpgradeContext context) { + private boolean isQualified(Database server, UpgradeContext context) { boolean v1TableExists = AspectStorageValidationUtil.checkV1TableExists(server); if (v1TableExists) { context.report().addLine("-- V1 table exists"); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/DeleteAspectTableStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/DeleteAspectTableStep.java index 2d435cdc28a6b9..8005e31e01c671 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/DeleteAspectTableStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/DeleteAspectTableStep.java @@ -4,16 +4,16 @@ import com.linkedin.datahub.upgrade.UpgradeStep; import com.linkedin.datahub.upgrade.UpgradeStepResult; import com.linkedin.datahub.upgrade.impl.DefaultUpgradeStepResult; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.function.Function; // Do we need SQL-tech specific migration paths? public class DeleteAspectTableStep implements UpgradeStep { - private final EbeanServer _server; + private final Database _server; - public DeleteAspectTableStep(final EbeanServer server) { + public DeleteAspectTableStep(final Database server) { _server = server; } @@ -31,7 +31,7 @@ public int retryCount() { public Function executable() { return (context) -> { try { - _server.execute(_server.createSqlUpdate("DROP TABLE IF EXISTS metadata_aspect;")); + _server.execute(_server.sqlUpdate("DROP TABLE IF EXISTS metadata_aspect;")); } catch (Exception e) { context.report().addLine("Failed to delete data from legacy table metadata_aspect", e); return new DefaultUpgradeStepResult( diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeCleanupUpgrade.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeCleanupUpgrade.java index c9a13c2208a569..2b5e23c5f82690 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeCleanupUpgrade.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeCleanupUpgrade.java @@ -5,7 +5,7 @@ import com.linkedin.datahub.upgrade.UpgradeStep; import com.linkedin.metadata.graph.GraphService; import com.linkedin.metadata.utils.elasticsearch.IndexConvention; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -17,8 +17,8 @@ public class NoCodeCleanupUpgrade implements Upgrade { private final List _steps; private final List _cleanupSteps; - // Upgrade requires the EbeanServer. - public NoCodeCleanupUpgrade(final EbeanServer server, final GraphService graphClient, + // Upgrade requires the Database. + public NoCodeCleanupUpgrade(final Database server, final GraphService graphClient, final RestHighLevelClient searchClient, final IndexConvention indexConvention) { _steps = buildUpgradeSteps(server, graphClient, searchClient, indexConvention); _cleanupSteps = buildCleanupSteps(); @@ -43,7 +43,7 @@ private List buildCleanupSteps() { return Collections.emptyList(); } - private List buildUpgradeSteps(final EbeanServer server, final GraphService graphClient, + private List buildUpgradeSteps(final Database server, final GraphService graphClient, final RestHighLevelClient searchClient, final IndexConvention indexConvention) { final List steps = new ArrayList<>(); steps.add(new NoCodeUpgradeQualificationStep(server)); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeUpgradeQualificationStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeUpgradeQualificationStep.java index 52e299d68b45a1..67a226f8f0676c 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeUpgradeQualificationStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/nocodecleanup/NoCodeUpgradeQualificationStep.java @@ -5,15 +5,15 @@ import com.linkedin.datahub.upgrade.UpgradeStepResult; import com.linkedin.datahub.upgrade.impl.DefaultUpgradeStepResult; import com.linkedin.metadata.entity.ebean.AspectStorageValidationUtil; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.function.Function; public class NoCodeUpgradeQualificationStep implements UpgradeStep { - private final EbeanServer _server; + private final Database _server; - NoCodeUpgradeQualificationStep(EbeanServer server) { + NoCodeUpgradeQualificationStep(Database server) { _server = server; } diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/ClearAspectV2TableStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/ClearAspectV2TableStep.java index 711cccf742254c..0303739e62afec 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/ClearAspectV2TableStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/ClearAspectV2TableStep.java @@ -5,7 +5,7 @@ import com.linkedin.datahub.upgrade.UpgradeStepResult; import com.linkedin.datahub.upgrade.impl.DefaultUpgradeStepResult; import com.linkedin.metadata.entity.ebean.EbeanAspectV2; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.function.Function; @@ -14,9 +14,9 @@ */ public class ClearAspectV2TableStep implements UpgradeStep { - private final EbeanServer _server; + private final Database _server; - public ClearAspectV2TableStep(final EbeanServer server) { + public ClearAspectV2TableStep(final Database server) { _server = server; } diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreBackup.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreBackup.java index a9dfa948c7873d..67718a6739beb8 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreBackup.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreBackup.java @@ -14,7 +14,7 @@ import com.linkedin.metadata.graph.GraphService; import com.linkedin.metadata.models.registry.EntityRegistry; import com.linkedin.metadata.search.EntitySearchService; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.ArrayList; import java.util.List; @@ -24,7 +24,7 @@ public class RestoreBackup implements Upgrade { private final List _steps; public RestoreBackup( - final EbeanServer server, + final Database server, final EntityService entityService, final EntityRegistry entityRegistry, final Authentication systemAuthentication, @@ -45,7 +45,7 @@ public List steps() { } private List buildSteps( - final EbeanServer server, + final Database server, final EntityService entityService, final EntityRegistry entityRegistry, final Authentication systemAuthentication, diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreStorageStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreStorageStep.java index f22a52c4877f6d..42f7f0073e59b5 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreStorageStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restorebackup/RestoreStorageStep.java @@ -20,6 +20,8 @@ import com.linkedin.metadata.models.AspectSpec; import com.linkedin.metadata.models.EntitySpec; import com.linkedin.metadata.models.registry.EntityRegistry; +import com.linkedin.util.Pair; + import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.util.ArrayList; @@ -181,8 +183,7 @@ private void readerExecutable(ReaderWrapper reader, UpgradeContext context) { final long version = aspect.getKey().getVersion(); final AuditStamp auditStamp = toAuditStamp(aspect); futureList.add(_gmsThreadPool.submit(() -> - _entityService.updateAspect(urn, entityName, aspectName, aspectSpec, aspectRecord, auditStamp, - version, version == 0L))); + _entityService.ingestAspects(urn, List.of(Pair.of(aspectName, aspectRecord)), auditStamp, null).get(0).getNewValue())); if (numRows % REPORT_BATCH_SIZE == 0) { for (Future future : futureList) { try { diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/RestoreIndices.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/RestoreIndices.java index 9e11a953079a50..3c0a9762a28c92 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/RestoreIndices.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/RestoreIndices.java @@ -10,7 +10,7 @@ import com.linkedin.metadata.graph.GraphService; import com.linkedin.metadata.models.registry.EntityRegistry; import com.linkedin.metadata.search.EntitySearchService; -import io.ebean.EbeanServer; +import io.ebean.Database; import java.util.ArrayList; import java.util.List; @@ -25,9 +25,11 @@ public class RestoreIndices implements Upgrade { public static final String URN_ARG_NAME = "urn"; public static final String URN_LIKE_ARG_NAME = "urnLike"; + public static final String STARTING_OFFSET_ARG_NAME = "startingOffset"; + private final List _steps; - public RestoreIndices(final EbeanServer server, final EntityService entityService, + public RestoreIndices(final Database server, final EntityService entityService, final EntityRegistry entityRegistry, final EntitySearchService entitySearchService, final GraphService graphService) { _steps = buildSteps(server, entityService, entityRegistry, entitySearchService, graphService); @@ -43,7 +45,7 @@ public List steps() { return _steps; } - private List buildSteps(final EbeanServer server, final EntityService entityService, + private List buildSteps(final Database server, final EntityService entityService, final EntityRegistry entityRegistry, final EntitySearchService entitySearchService, final GraphService graphService) { final List steps = new ArrayList<>(); diff --git a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/SendMAEStep.java b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/SendMAEStep.java index ac2457732771d0..2ac4fea2e653ac 100644 --- a/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/SendMAEStep.java +++ b/datahub-upgrade/src/main/java/com/linkedin/datahub/upgrade/restoreindices/SendMAEStep.java @@ -9,7 +9,7 @@ import com.linkedin.metadata.entity.restoreindices.RestoreIndicesArgs; import com.linkedin.metadata.entity.restoreindices.RestoreIndicesResult; import com.linkedin.metadata.models.registry.EntityRegistry; -import io.ebean.EbeanServer; +import io.ebean.Database; import io.ebean.ExpressionList; import java.util.ArrayList; @@ -30,9 +30,11 @@ public class SendMAEStep implements UpgradeStep { private static final int DEFAULT_BATCH_SIZE = 1000; private static final long DEFAULT_BATCH_DELAY_MS = 250; + + private static final int DEFAULT_STARTING_OFFSET = 0; private static final int DEFAULT_THREADS = 1; - private final EbeanServer _server; + private final Database _server; private final EntityService _entityService; public class KafkaJob implements Callable { @@ -48,7 +50,7 @@ public RestoreIndicesResult call() { } } - public SendMAEStep(final EbeanServer server, final EntityService entityService, final EntityRegistry entityRegistry) { + public SendMAEStep(final Database server, final EntityService entityService, final EntityRegistry entityRegistry) { _server = server; _entityService = entityService; } @@ -83,6 +85,7 @@ private RestoreIndicesArgs getArgs(UpgradeContext context) { result.batchSize = getBatchSize(context.parsedArgs()); result.numThreads = getThreadCount(context.parsedArgs()); result.batchDelayMs = getBatchDelayMs(context.parsedArgs()); + result.start = getStartingOffset(context.parsedArgs()); if (containsKey(context.parsedArgs(), RestoreIndices.ASPECT_NAME_ARG_NAME)) { result.aspectName = context.parsedArgs().get(RestoreIndices.ASPECT_NAME_ARG_NAME).get(); } @@ -124,7 +127,7 @@ public Function executable() { final int rowCount = getRowCount(args); context.report().addLine(String.format("Found %s latest aspects in aspects table in %.2f minutes.", rowCount, (float) (System.currentTimeMillis() - startTime) / 1000 / 60)); - int start = 0; + int start = args.start; List> futures = new ArrayList<>(); startTime = System.currentTimeMillis(); @@ -186,6 +189,10 @@ private int getBatchSize(final Map> parsedArgs) { return getInt(parsedArgs, DEFAULT_BATCH_SIZE, RestoreIndices.BATCH_SIZE_ARG_NAME); } + private int getStartingOffset(final Map> parsedArgs) { + return getInt(parsedArgs, DEFAULT_STARTING_OFFSET, RestoreIndices.STARTING_OFFSET_ARG_NAME); + } + private long getBatchDelayMs(final Map> parsedArgs) { long resolvedBatchDelayMs = DEFAULT_BATCH_DELAY_MS; if (containsKey(parsedArgs, RestoreIndices.BATCH_DELAY_MS_ARG_NAME)) { diff --git a/datahub-upgrade/src/test/java/com/linkedin/datahub/upgrade/UpgradeCliApplicationTestConfiguration.java b/datahub-upgrade/src/test/java/com/linkedin/datahub/upgrade/UpgradeCliApplicationTestConfiguration.java index fefc853be8c0b3..b1bdead58a72b5 100644 --- a/datahub-upgrade/src/test/java/com/linkedin/datahub/upgrade/UpgradeCliApplicationTestConfiguration.java +++ b/datahub-upgrade/src/test/java/com/linkedin/datahub/upgrade/UpgradeCliApplicationTestConfiguration.java @@ -6,7 +6,7 @@ import com.linkedin.metadata.models.registry.ConfigEntityRegistry; import com.linkedin.metadata.models.registry.EntityRegistry; import com.linkedin.metadata.search.SearchService; -import io.ebean.EbeanServer; +import io.ebean.Database; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -19,7 +19,7 @@ public class UpgradeCliApplicationTestConfiguration { private UpgradeCli upgradeCli; @MockBean - private EbeanServer ebeanServer; + private Database ebeanServer; @MockBean private EntityService _entityService; diff --git a/datahub-web-react/README.md b/datahub-web-react/README.md index 6c91b169af858f..8bf592b11a0aec 100644 --- a/datahub-web-react/README.md +++ b/datahub-web-react/README.md @@ -126,7 +126,9 @@ for functional configurability should reside. to render a view associated with a particular entity type (user, dataset, etc.). -![entity-registry](./entity-registry.png) +

+ +

**graphql** - The React App talks to the `dathub-frontend` server using GraphQL. This module is where the *queries* issued against the server are defined. Once defined, running `yarn run generate` will code-gen TypeScript objects to make invoking diff --git a/datahub-web-react/package.json b/datahub-web-react/package.json index 107b1b08927db7..2d9329919fdc1b 100644 --- a/datahub-web-react/package.json +++ b/datahub-web-react/package.json @@ -38,7 +38,7 @@ "@vx/shape": "^0.0.199", "@vx/tooltip": "^0.0.199", "@vx/zoom": "^0.0.199", - "analytics": "^0.7.5", + "analytics": "^0.8.9", "antd": "4.24.7", "color-hash": "^2.0.1", "craco-antd": "^1.19.0", diff --git a/datahub-web-react/public/robots.txt b/datahub-web-react/public/robots.txt index e9e57dc4d41b9b..7a00656bc30738 100644 --- a/datahub-web-react/public/robots.txt +++ b/datahub-web-react/public/robots.txt @@ -1,3 +1,6 @@ # https://www.robotstxt.org/robotstxt.html User-agent: * -Disallow: +Disallow: /api +Disallow: /gms +Disallow: /search +Disallow: /logOut diff --git a/datahub-web-react/src/App.tsx b/datahub-web-react/src/App.tsx index 68a4b93d714810..b6bc608dccbbb0 100644 --- a/datahub-web-react/src/App.tsx +++ b/datahub-web-react/src/App.tsx @@ -35,6 +35,7 @@ import GlossaryNodeEntity from './app/entity/glossaryNode/GlossaryNodeEntity'; import { DataPlatformEntity } from './app/entity/dataPlatform/DataPlatformEntity'; import { DataProductEntity } from './app/entity/dataProduct/DataProductEntity'; import { DataPlatformInstanceEntity } from './app/entity/dataPlatformInstance/DataPlatformInstanceEntity'; +import { RoleEntity } from './app/entity/Access/RoleEntity'; /* Construct Apollo Client @@ -116,6 +117,7 @@ const App: React.VFC = () => { register.register(new DomainEntity()); register.register(new ContainerEntity()); register.register(new GlossaryNodeEntity()); + register.register(new RoleEntity()); register.register(new DataPlatformEntity()); register.register(new DataProductEntity()); register.register(new DataPlatformInstanceEntity()); diff --git a/datahub-web-react/src/Mocks.tsx b/datahub-web-react/src/Mocks.tsx index dcefc7f70d7857..a2e14308e8cee2 100644 --- a/datahub-web-react/src/Mocks.tsx +++ b/datahub-web-react/src/Mocks.tsx @@ -1973,6 +1973,7 @@ export const mocks = [ count: 10, filters: [], orFilters: [], + searchFlags: { getSuggestions: true }, }, }, }, @@ -2033,6 +2034,7 @@ export const mocks = [ ], }, ], + suggestions: [], }, } as GetSearchResultsQuery, }, @@ -2059,6 +2061,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -2112,6 +2115,7 @@ export const mocks = [ ], }, ], + suggestions: [], }, } as GetSearchResultsQuery, }, @@ -2230,6 +2234,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -2251,6 +2256,7 @@ export const mocks = [ insights: [], }, ], + suggestions: [], facets: [ { field: 'origin', @@ -2772,6 +2778,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -2794,6 +2801,7 @@ export const mocks = [ insights: [], }, ], + suggestions: [], facets: [ { __typename: 'FacetMetadata', @@ -2886,6 +2894,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -2908,6 +2917,7 @@ export const mocks = [ }, ], facets: [], + suggestions: [], }, } as GetSearchResultsForMultipleQuery, }, @@ -2934,6 +2944,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -2955,6 +2966,7 @@ export const mocks = [ insights: [], }, ], + suggestions: [], facets: [ { field: 'origin', @@ -3007,6 +3019,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -3028,6 +3041,7 @@ export const mocks = [ insights: [], }, ], + suggestions: [], facets: [ { field: 'origin', @@ -3084,6 +3098,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -3113,6 +3128,7 @@ export const mocks = [ insights: [], }, ], + suggestions: [], facets: [ { field: 'origin', @@ -3175,6 +3191,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -3196,6 +3213,7 @@ export const mocks = [ insights: [], }, ], + suggestions: [], facets: [ { field: 'origin', @@ -3258,6 +3276,7 @@ export const mocks = [ ], }, ], + searchFlags: { getSuggestions: true }, }, }, }, @@ -3279,6 +3298,7 @@ export const mocks = [ insights: [], }, ], + suggestions: [], facets: [ { field: 'origin', @@ -3363,6 +3383,7 @@ export const mocks = [ generatePersonalAccessTokens: true, manageGlobalViews: true, manageOwnershipTypes: true, + manageGlobalAnnouncements: true, }, }, }, @@ -3450,6 +3471,7 @@ export const mocks = [ count: 10, filters: [], orFilters: [], + searchFlags: { getSuggestions: true }, }, }, }, @@ -3461,6 +3483,7 @@ export const mocks = [ total: 0, searchResults: [], facets: [], + suggestions: [], }, }, }, @@ -3609,4 +3632,5 @@ export const platformPrivileges: PlatformPrivileges = { createDomains: true, manageGlobalViews: true, manageOwnershipTypes: true, + manageGlobalAnnouncements: true, }; diff --git a/datahub-web-react/src/app/SearchRoutes.tsx b/datahub-web-react/src/app/SearchRoutes.tsx index 82606befd2663f..d2ad4ab6f4db19 100644 --- a/datahub-web-react/src/app/SearchRoutes.tsx +++ b/datahub-web-react/src/app/SearchRoutes.tsx @@ -8,20 +8,27 @@ import { EntityPage } from './entity/EntityPage'; import { BrowseResultsPage } from './browse/BrowseResultsPage'; import { SearchPage } from './search/SearchPage'; import { AnalyticsPage } from './analyticsDashboard/components/AnalyticsPage'; -import { ManageDomainsPage } from './domain/ManageDomainsPage'; import { ManageIngestionPage } from './ingest/ManageIngestionPage'; import GlossaryRoutes from './glossary/GlossaryRoutes'; import { SettingsPage } from './settings/SettingsPage'; +import DomainRoutes from './domain/DomainRoutes'; +import { useIsNestedDomainsEnabled } from './useAppConfig'; +import { ManageDomainsPage } from './domain/ManageDomainsPage'; /** * Container for all searchable page routes */ export const SearchRoutes = (): JSX.Element => { const entityRegistry = useEntityRegistry(); + const isNestedDomainsEnabled = useIsNestedDomainsEnabled(); + const entities = isNestedDomainsEnabled + ? entityRegistry.getEntitiesForSearchRoutes() + : entityRegistry.getNonGlossaryEntities(); + return ( - {entityRegistry.getNonGlossaryEntities().map((entity) => ( + {entities.map((entity) => ( { /> } /> } /> - } /> + {isNestedDomainsEnabled && } />} + {!isNestedDomainsEnabled && } />} } /> } /> } /> diff --git a/datahub-web-react/src/app/analytics/event.ts b/datahub-web-react/src/app/analytics/event.ts index 84173b522fb072..28cd61ff3171a9 100644 --- a/datahub-web-react/src/app/analytics/event.ts +++ b/datahub-web-react/src/app/analytics/event.ts @@ -55,6 +55,7 @@ export enum EventType { ShowStandardHomepageEvent, CreateGlossaryEntityEvent, CreateDomainEvent, + MoveDomainEvent, CreateIngestionSourceEvent, UpdateIngestionSourceEvent, DeleteIngestionSourceEvent, @@ -454,6 +455,13 @@ export interface CreateGlossaryEntityEvent extends BaseEvent { export interface CreateDomainEvent extends BaseEvent { type: EventType.CreateDomainEvent; + parentDomainUrn?: string; +} + +export interface MoveDomainEvent extends BaseEvent { + type: EventType.MoveDomainEvent; + oldParentDomainUrn?: string; + parentDomainUrn?: string; } // Managed Ingestion Events @@ -653,6 +661,7 @@ export type Event = | ShowStandardHomepageEvent | CreateGlossaryEntityEvent | CreateDomainEvent + | MoveDomainEvent | CreateIngestionSourceEvent | UpdateIngestionSourceEvent | DeleteIngestionSourceEvent diff --git a/datahub-web-react/src/app/domain/CreateDomainModal.tsx b/datahub-web-react/src/app/domain/CreateDomainModal.tsx index 9fd24b551c0afa..ca1bc305960035 100644 --- a/datahub-web-react/src/app/domain/CreateDomainModal.tsx +++ b/datahub-web-react/src/app/domain/CreateDomainModal.tsx @@ -5,9 +5,12 @@ import { useCreateDomainMutation } from '../../graphql/domain.generated'; import { useEnterKeyListener } from '../shared/useEnterKeyListener'; import { validateCustomUrnId } from '../shared/textUtil'; import analytics, { EventType } from '../analytics'; +import DomainParentSelect from '../entity/shared/EntityDropdown/DomainParentSelect'; +import { useIsNestedDomainsEnabled } from '../useAppConfig'; +import { useDomainsContext } from './DomainsContext'; const SuggestedNamesGroup = styled.div` - margin-top: 12px; + margin-top: 8px; `; const ClickableTag = styled(Tag)` @@ -16,9 +19,38 @@ const ClickableTag = styled(Tag)` } `; +const FormItem = styled(Form.Item)` + .ant-form-item-label { + padding-bottom: 2px; + } +`; + +const FormItemWithMargin = styled(FormItem)` + margin-bottom: 16px; +`; + +const FormItemNoMargin = styled(FormItem)` + margin-bottom: 0; +`; + +const FormItemLabel = styled(Typography.Text)` + font-weight: 600; + color: #373d44; +`; + +const AdvancedLabel = styled(Typography.Text)` + color: #373d44; +`; + type Props = { onClose: () => void; - onCreate: (urn: string, id: string | undefined, name: string, description: string | undefined) => void; + onCreate: ( + urn: string, + id: string | undefined, + name: string, + description: string | undefined, + parentDomain?: string, + ) => void; }; const SUGGESTED_DOMAIN_NAMES = ['Engineering', 'Marketing', 'Sales', 'Product']; @@ -28,7 +60,12 @@ const NAME_FIELD_NAME = 'name'; const DESCRIPTION_FIELD_NAME = 'description'; export default function CreateDomainModal({ onClose, onCreate }: Props) { + const isNestedDomainsEnabled = useIsNestedDomainsEnabled(); const [createDomainMutation] = useCreateDomainMutation(); + const { entityData } = useDomainsContext(); + const [selectedParentUrn, setSelectedParentUrn] = useState( + (isNestedDomainsEnabled && entityData?.urn) || '', + ); const [createButtonEnabled, setCreateButtonEnabled] = useState(false); const [form] = Form.useForm(); @@ -39,6 +76,7 @@ export default function CreateDomainModal({ onClose, onCreate }: Props) { id: form.getFieldValue(ID_FIELD_NAME), name: form.getFieldValue(NAME_FIELD_NAME), description: form.getFieldValue(DESCRIPTION_FIELD_NAME), + parentDomain: selectedParentUrn || undefined, }, }, }) @@ -46,6 +84,7 @@ export default function CreateDomainModal({ onClose, onCreate }: Props) { if (!errors) { analytics.event({ type: EventType.CreateDomainEvent, + parentDomainUrn: selectedParentUrn || undefined, }); message.success({ content: `Created domain!`, @@ -56,6 +95,7 @@ export default function CreateDomainModal({ onClose, onCreate }: Props) { form.getFieldValue(ID_FIELD_NAME), form.getFieldValue(NAME_FIELD_NAME), form.getFieldValue(DESCRIPTION_FIELD_NAME), + selectedParentUrn || undefined, ); form.resetFields(); } @@ -74,7 +114,7 @@ export default function CreateDomainModal({ onClose, onCreate }: Props) { return ( field.errors.length > 0)); }} > - Name}> - Give your new Domain a name. - Parent (optional)}> + + + )} + Name}> + - + {SUGGESTED_DOMAIN_NAMES.map((name) => { return ( @@ -134,29 +181,29 @@ export default function CreateDomainModal({ onClose, onCreate }: Props) { ); })} - - Description}> - - An optional description for your new domain. You can change this later. - - + Description} + help="You can always change the description later." + > + - - + + - Advanced} key="1"> - Domain Id}> - - By default, a random UUID will be generated to uniquely identify this domain. If - you'd like to provide a custom id instead to more easily keep track of this domain, + Advanced Options} key="1"> + Domain Id} + help="By default, a random UUID will be generated to uniquely identify this domain. If + you'd like to provide a custom id instead to more easily keep track of this domain, you may provide it here. Be careful, you cannot easily change the domain id after - creation. - - + ({ @@ -170,8 +217,8 @@ export default function CreateDomainModal({ onClose, onCreate }: Props) { ]} > - - + + diff --git a/datahub-web-react/src/app/domain/DomainIcon.tsx b/datahub-web-react/src/app/domain/DomainIcon.tsx new file mode 100644 index 00000000000000..0fe9892f0c281f --- /dev/null +++ b/datahub-web-react/src/app/domain/DomainIcon.tsx @@ -0,0 +1,11 @@ +import Icon from '@ant-design/icons/lib/components/Icon'; +import React from 'react'; +import { ReactComponent as DomainsIcon } from '../../images/domain.svg'; + +type Props = { + style?: React.CSSProperties; +}; + +export default function DomainIcon({ style }: Props) { + return ; +} diff --git a/datahub-web-react/src/app/domain/DomainRoutes.tsx b/datahub-web-react/src/app/domain/DomainRoutes.tsx new file mode 100644 index 00000000000000..56811ddc48c0c6 --- /dev/null +++ b/datahub-web-react/src/app/domain/DomainRoutes.tsx @@ -0,0 +1,39 @@ +import React, { useState } from 'react'; +import styled from 'styled-components/macro'; +import { Switch, Route } from 'react-router-dom'; +import { PageRoutes } from '../../conf/Global'; +import { EntityPage } from '../entity/EntityPage'; +import { useEntityRegistry } from '../useEntityRegistry'; +import ManageDomainsPageV2 from './nestedDomains/ManageDomainsPageV2'; +import { EntityType } from '../../types.generated'; +import ManageDomainsSidebar from './nestedDomains/ManageDomainsSidebar'; +import { DomainsContext } from './DomainsContext'; +import { GenericEntityProperties } from '../entity/shared/types'; + +const ContentWrapper = styled.div` + display: flex; + flex: 1; + overflow: hidden; +`; + +export default function DomainRoutes() { + const entityRegistry = useEntityRegistry(); + const [entityData, setEntityData] = useState(null); + const [parentDomainsToUpdate, setParentDomainsToUpdate] = useState([]); + + return ( + + + + + } + /> + } /> + + + + ); +} diff --git a/datahub-web-react/src/app/domain/DomainSearch.tsx b/datahub-web-react/src/app/domain/DomainSearch.tsx new file mode 100644 index 00000000000000..e82dae9c2c9e69 --- /dev/null +++ b/datahub-web-react/src/app/domain/DomainSearch.tsx @@ -0,0 +1,143 @@ +import React, { CSSProperties, useRef, useState } from 'react'; +import { Link } from 'react-router-dom'; +import styled from 'styled-components/macro'; +import Highlight from 'react-highlighter'; +import { useGetSearchResultsForMultipleQuery } from '../../graphql/search.generated'; +import { EntityType } from '../../types.generated'; +import { IconStyleType } from '../entity/Entity'; +import { ANTD_GRAY } from '../entity/shared/constants'; +import { SearchBar } from '../search/SearchBar'; +import ClickOutside from '../shared/ClickOutside'; +import { useEntityRegistry } from '../useEntityRegistry'; +import DomainIcon from './DomainIcon'; +import ParentEntities from '../search/filters/ParentEntities'; +import { getParentDomains } from './utils'; + +const DomainSearchWrapper = styled.div` + position: relative; +`; + +const ResultsWrapper = styled.div` + background-color: white; + border-radius: 5px; + box-shadow: 0 3px 6px -4px rgb(0 0 0 / 12%), 0 6px 16px 0 rgb(0 0 0 / 8%), 0 9px 28px 8px rgb(0 0 0 / 5%); + max-height: 380px; + overflow: auto; + padding: 8px; + position: absolute; + max-height: 210px; + overflow: auto; + width: calc(100% - 24px); + left: 12px; + top: 45px; + z-index: 1; +`; + +const SearchResult = styled(Link)` + color: #262626; + display: flex; + align-items: center; + gap: 8px; + height: 100%; + padding: 6px 8px; + width: 100%; + &:hover { + background-color: ${ANTD_GRAY[3]}; + color: #262626; + } +`; + +const IconWrapper = styled.span``; + +const highlightMatchStyle: CSSProperties = { + fontWeight: 'bold', + background: 'none', + padding: 0, +}; + +function DomainSearch() { + const [query, setQuery] = useState(''); + const [isSearchBarFocused, setIsSearchBarFocused] = useState(false); + const entityRegistry = useEntityRegistry(); + + const { data } = useGetSearchResultsForMultipleQuery({ + variables: { + input: { + types: [EntityType.Domain], + query, + start: 0, + count: 50, + }, + }, + skip: !query, + }); + + const searchResults = data?.searchAcrossEntities?.searchResults; + const timerRef = useRef(-1); + const handleQueryChange = (q: string) => { + window.clearTimeout(timerRef.current); + timerRef.current = window.setTimeout(() => { + setQuery(q); + }, 250); + }; + + return ( + + setIsSearchBarFocused(false)}> + null} + onQueryChange={(q) => handleQueryChange(q)} + entityRegistry={entityRegistry} + onFocus={() => setIsSearchBarFocused(true)} + /> + {isSearchBarFocused && searchResults && !!searchResults.length && ( + + {searchResults.map((result) => { + return ( + setIsSearchBarFocused(false)} + > + + {result.entity.type === EntityType.Domain ? ( + + ) : ( + entityRegistry.getIcon(result.entity.type, 12, IconStyleType.ACCENT) + )} + +
+ + + {entityRegistry.getDisplayName(result.entity.type, result.entity)} + +
+
+ ); + })} +
+ )} +
+
+ ); +} + +export default DomainSearch; diff --git a/datahub-web-react/src/app/domain/DomainsContext.tsx b/datahub-web-react/src/app/domain/DomainsContext.tsx new file mode 100644 index 00000000000000..ecbdaebd03817b --- /dev/null +++ b/datahub-web-react/src/app/domain/DomainsContext.tsx @@ -0,0 +1,21 @@ +import React, { useContext } from 'react'; +import { GenericEntityProperties } from '../entity/shared/types'; + +export interface DomainsContextType { + entityData: GenericEntityProperties | null; + setEntityData: (entityData: GenericEntityProperties | null) => void; + parentDomainsToUpdate: string[]; + setParentDomainsToUpdate: (values: string[]) => void; +} + +export const DomainsContext = React.createContext({ + entityData: null, + setEntityData: () => {}, + parentDomainsToUpdate: [], // used to tell domains to refetch their children count after updates (create, move, delete) + setParentDomainsToUpdate: () => {}, +}); + +export const useDomainsContext = () => { + const { entityData, setEntityData, parentDomainsToUpdate, setParentDomainsToUpdate } = useContext(DomainsContext); + return { entityData, setEntityData, parentDomainsToUpdate, setParentDomainsToUpdate }; +}; diff --git a/datahub-web-react/src/app/domain/DomainsList.tsx b/datahub-web-react/src/app/domain/DomainsList.tsx index f5fea36e32bda8..b1095726808fe8 100644 --- a/datahub-web-react/src/app/domain/DomainsList.tsx +++ b/datahub-web-react/src/app/domain/DomainsList.tsx @@ -18,8 +18,8 @@ import { OnboardingTour } from '../onboarding/OnboardingTour'; import { DOMAINS_INTRO_ID, DOMAINS_CREATE_DOMAIN_ID } from '../onboarding/config/DomainsOnboardingConfig'; import { getElasticCappedTotalValueText } from '../entity/shared/constants'; import { StyledTable } from '../entity/shared/components/styled/StyledTable'; -import { IconStyleType } from '../entity/Entity'; import { DomainOwnersColumn, DomainListMenuColumn, DomainNameColumn } from './DomainListColumns'; +import DomainIcon from './DomainIcon'; const DomainsContainer = styled.div``; @@ -82,7 +82,6 @@ export const DomainsList = () => { }, 2000); }; - const logoIcon = entityRegistry.getIcon(EntityType.Domain, 12, IconStyleType.ACCENT); const allColumns = [ { title: 'Name', @@ -91,7 +90,14 @@ export const DomainsList = () => { sorter: (sourceA, sourceB) => { return sourceA.name.localeCompare(sourceB.name); }, - render: DomainNameColumn(logoIcon), + render: DomainNameColumn( + , + ), }, { title: 'Owners', diff --git a/datahub-web-react/src/app/domain/ManageDomainsPage.tsx b/datahub-web-react/src/app/domain/ManageDomainsPage.tsx index 6172ac0246f58e..3e19da18750371 100644 --- a/datahub-web-react/src/app/domain/ManageDomainsPage.tsx +++ b/datahub-web-react/src/app/domain/ManageDomainsPage.tsx @@ -1,7 +1,9 @@ import { Typography } from 'antd'; -import React from 'react'; +import React, { useState } from 'react'; import styled from 'styled-components'; import { DomainsList } from './DomainsList'; +import { DomainsContext } from './DomainsContext'; +import { GenericEntityProperties } from '../entity/shared/types'; const PageContainer = styled.div` padding-top: 20px; @@ -22,17 +24,22 @@ const PageTitle = styled(Typography.Title)` const ListContainer = styled.div``; export const ManageDomainsPage = () => { + const [entityData, setEntityData] = useState(null); + const [parentDomainsToUpdate, setParentDomainsToUpdate] = useState([]); + return ( - - - Domains - - View your DataHub Domains. Take administrative actions. - - - - - - + + + + Domains + + View your DataHub Domains. Take administrative actions. + + + + + + + ); }; diff --git a/datahub-web-react/src/app/domain/nestedDomains/DomainsSidebarHeader.tsx b/datahub-web-react/src/app/domain/nestedDomains/DomainsSidebarHeader.tsx new file mode 100644 index 00000000000000..d9ff18514d8cfe --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/DomainsSidebarHeader.tsx @@ -0,0 +1,58 @@ +import { useApolloClient } from '@apollo/client'; +import { PlusOutlined } from '@ant-design/icons'; +import { Button } from 'antd'; +import React, { useState } from 'react'; +import { Link } from 'react-router-dom'; +import styled from 'styled-components'; +import { ANTD_GRAY, ANTD_GRAY_V2 } from '../../entity/shared/constants'; +import DomainsTitle from './DomainsTitle'; +import { PageRoutes } from '../../../conf/Global'; +import CreateDomainModal from '../CreateDomainModal'; +import { updateListDomainsCache } from '../utils'; +import { useDomainsContext } from '../DomainsContext'; + +const HeaderWrapper = styled.div` + border-bottom: 1px solid ${ANTD_GRAY[4]}; + padding: 16px; + font-size: 20px; + display: flex; + align-items: center; + justify-content: space-between; +`; + +const StyledButton = styled(Button)` + box-shadow: none; + border-color: ${ANTD_GRAY_V2[6]}; +`; + +const StyledLink = styled(Link)` + color: inherit; + + &:hover { + color: inherit; + } +`; + +export default function DomainsSidebarHeader() { + const { setParentDomainsToUpdate } = useDomainsContext(); + const [isCreatingDomain, setIsCreatingDomain] = useState(false); + const client = useApolloClient(); + + return ( + + + + + } onClick={() => setIsCreatingDomain(true)} /> + {isCreatingDomain && ( + setIsCreatingDomain(false)} + onCreate={(urn, id, name, description, parentDomain) => { + updateListDomainsCache(client, urn, id, name, description, parentDomain); + if (parentDomain) setParentDomainsToUpdate([parentDomain]); + }} + /> + )} + + ); +} diff --git a/datahub-web-react/src/app/domain/nestedDomains/DomainsTitle.tsx b/datahub-web-react/src/app/domain/nestedDomains/DomainsTitle.tsx new file mode 100644 index 00000000000000..3aa7c8330d0797 --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/DomainsTitle.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import styled from 'styled-components'; +import DomainIcon from '../DomainIcon'; + +const IconWrapper = styled.span` + margin-right: 10px; +`; + +export default function DomainsTitle() { + return ( + + + + + Domains + + ); +} diff --git a/datahub-web-react/src/app/domain/nestedDomains/ManageDomainsPageV2.tsx b/datahub-web-react/src/app/domain/nestedDomains/ManageDomainsPageV2.tsx new file mode 100644 index 00000000000000..486169c3559d30 --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/ManageDomainsPageV2.tsx @@ -0,0 +1,60 @@ +import { useApolloClient } from '@apollo/client'; +import { Button } from 'antd'; +import { PlusOutlined } from '@ant-design/icons'; +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components/macro'; +import DomainsTitle from './DomainsTitle'; +import RootDomains from './RootDomains'; +import { DOMAINS_CREATE_DOMAIN_ID, DOMAINS_INTRO_ID } from '../../onboarding/config/DomainsOnboardingConfig'; +import { OnboardingTour } from '../../onboarding/OnboardingTour'; +import { ANTD_GRAY_V2 } from '../../entity/shared/constants'; +import CreateDomainModal from '../CreateDomainModal'; +import { updateListDomainsCache } from '../utils'; +import { useDomainsContext } from '../DomainsContext'; + +const PageWrapper = styled.div` + background-color: ${ANTD_GRAY_V2[1]}; + flex: 1; + display: flex; + flex-direction: column; +`; + +const Header = styled.div` + display: flex; + justify-content: space-between; + padding: 32px 24px; + font-size: 30px; + align-items: center; +`; + +export default function ManageDomainsPageV2() { + const { setEntityData, setParentDomainsToUpdate } = useDomainsContext(); + const [isCreatingDomain, setIsCreatingDomain] = useState(false); + const client = useApolloClient(); + + useEffect(() => { + setEntityData(null); + }, [setEntityData]); + + return ( + + +
+ + +
+ + {isCreatingDomain && ( + setIsCreatingDomain(false)} + onCreate={(urn, id, name, description, parentDomain) => { + updateListDomainsCache(client, urn, id, name, description, parentDomain); + if (parentDomain) setParentDomainsToUpdate([parentDomain]); + }} + /> + )} +
+ ); +} diff --git a/datahub-web-react/src/app/domain/nestedDomains/ManageDomainsSidebar.tsx b/datahub-web-react/src/app/domain/nestedDomains/ManageDomainsSidebar.tsx new file mode 100644 index 00000000000000..827031138dcdb9 --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/ManageDomainsSidebar.tsx @@ -0,0 +1,28 @@ +import React, { useState } from 'react'; +import { MAX_BROWSER_WIDTH, MIN_BROWSWER_WIDTH } from '../../glossary/BusinessGlossaryPage'; +import { ProfileSidebarResizer } from '../../entity/shared/containers/profile/sidebar/ProfileSidebarResizer'; +import DomainsSidebarHeader from './DomainsSidebarHeader'; +import { SidebarWrapper } from '../../shared/sidebar/components'; +import DomainNavigator from './domainNavigator/DomainNavigator'; +import DomainSearch from '../DomainSearch'; + +export default function ManageDomainsSidebar() { + const [browserWidth, setBrowserWith] = useState(window.innerWidth * 0.2); + + return ( + <> + + + + + + + setBrowserWith(Math.min(Math.max(width, MIN_BROWSWER_WIDTH), MAX_BROWSER_WIDTH)) + } + initialSize={browserWidth} + isSidebarOnLeft + /> + + ); +} diff --git a/datahub-web-react/src/app/domain/nestedDomains/RootDomains.tsx b/datahub-web-react/src/app/domain/nestedDomains/RootDomains.tsx new file mode 100644 index 00000000000000..757119919e3367 --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/RootDomains.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import styled from 'styled-components'; +import { Message } from '../../shared/Message'; +import { ResultWrapper } from '../../search/SearchResultList'; +import { useEntityRegistry } from '../../useEntityRegistry'; +import { EntityType } from '../../../types.generated'; +import useListDomains from '../useListDomains'; + +const DomainsWrapper = styled.div` + overflow: auto; + padding: 0 28px 16px 28px; +`; + +export default function RootDomains() { + const entityRegistry = useEntityRegistry(); + const { loading, error, data, sortedDomains } = useListDomains({}); + + return ( + <> + {!data && loading && } + {error && } + + {sortedDomains?.map((domain) => ( + + {entityRegistry.renderSearchResult(EntityType.Domain, { entity: domain, matchedFields: [] })} + + ))} + + + ); +} diff --git a/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNavigator.tsx b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNavigator.tsx new file mode 100644 index 00000000000000..0fbcffb9a260c7 --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNavigator.tsx @@ -0,0 +1,37 @@ +import { Alert } from 'antd'; +import React from 'react'; +import styled from 'styled-components'; +import useListDomains from '../../useListDomains'; +import DomainNode from './DomainNode'; +import { Domain } from '../../../../types.generated'; + +const NavigatorWrapper = styled.div` + font-size: 14px; + max-height: calc(100% - 65px); + padding: 8px 8px 16px 16px; + overflow: auto; +`; + +interface Props { + domainUrnToHide?: string; + selectDomainOverride?: (domain: Domain) => void; +} + +export default function DomainNavigator({ domainUrnToHide, selectDomainOverride }: Props) { + const { sortedDomains, error } = useListDomains({}); + + return ( + + {error && } + {sortedDomains?.map((domain) => ( + + ))} + + ); +} diff --git a/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNode.tsx b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNode.tsx new file mode 100644 index 00000000000000..09c8e13853bb70 --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/DomainNode.tsx @@ -0,0 +1,137 @@ +import { Typography } from 'antd'; +import React, { useEffect, useMemo } from 'react'; +import { useHistory } from 'react-router'; +import styled from 'styled-components'; +import { Domain } from '../../../../types.generated'; +import { useEntityRegistry } from '../../../useEntityRegistry'; +import { RotatingTriangle } from '../../../shared/sidebar/components'; +import DomainIcon from '../../DomainIcon'; +import useListDomains from '../../useListDomains'; +import useToggle from '../../../shared/useToggle'; +import { BodyContainer, BodyGridExpander } from '../../../shared/components'; +import { ANTD_GRAY_V2 } from '../../../entity/shared/constants'; +import { useDomainsContext } from '../../DomainsContext'; +import { applyOpacity } from '../../../shared/styleUtils'; +import useHasDomainChildren from './useHasDomainChildren'; + +const RowWrapper = styled.div` + align-items: center; + display: flex; + padding: 2px 2px 4px 0; + overflow: hidden; +`; + +const NameWrapper = styled(Typography.Text)<{ isSelected: boolean; addLeftPadding: boolean }>` + flex: 1; + overflow: hidden; + padding: 2px; + ${(props) => + props.isSelected && `background-color: ${applyOpacity(props.theme.styles['primary-color'] || '', 10)};`} + ${(props) => props.addLeftPadding && 'padding-left: 22px;'} + + &:hover { + ${(props) => !props.isSelected && `background-color: ${ANTD_GRAY_V2[1]};`} + cursor: pointer; + } + + svg { + margin-right: 6px; + } +`; + +const ButtonWrapper = styled.span` + margin-right: 4px; + font-size: 16px; + height: 16px; + width: 16px; + + svg { + height: 10px; + width: 10px; + } + + .ant-btn { + height: 16px; + width: 16px; + } +`; + +const StyledExpander = styled(BodyGridExpander)` + padding-left: 24px; +`; + +interface Props { + domain: Domain; + numDomainChildren: number; + domainUrnToHide?: string; + selectDomainOverride?: (domain: Domain) => void; +} + +export default function DomainNode({ domain, numDomainChildren, domainUrnToHide, selectDomainOverride }: Props) { + const shouldHideDomain = domainUrnToHide === domain.urn; + const history = useHistory(); + const entityRegistry = useEntityRegistry(); + const { entityData } = useDomainsContext(); + const { isOpen, isClosing, toggle, toggleOpen } = useToggle({ + initialValue: false, + closeDelay: 250, + }); + const { sortedDomains } = useListDomains({ parentDomain: domain.urn, skip: !isOpen || shouldHideDomain }); + const isOnEntityPage = entityData && entityData.urn === domain.urn; + const displayName = entityRegistry.getDisplayName(domain.type, isOnEntityPage ? entityData : domain); + const isInSelectMode = !!selectDomainOverride; + const hasDomainChildren = useHasDomainChildren({ domainUrn: domain.urn, numDomainChildren }); + + const shouldAutoOpen = useMemo( + () => !isInSelectMode && entityData?.parentDomains?.domains.some((parent) => parent.urn === domain.urn), + [isInSelectMode, entityData, domain.urn], + ); + + useEffect(() => { + if (shouldAutoOpen) toggleOpen(); + }, [shouldAutoOpen, toggleOpen]); + + function handleSelectDomain() { + if (selectDomainOverride) { + selectDomainOverride(domain); + } else { + history.push(entityRegistry.getEntityUrl(domain.type, domain.urn)); + } + } + + if (shouldHideDomain) return null; + + return ( + <> + + {hasDomainChildren && ( + + + + )} + + {!isInSelectMode && } + {displayName} + + + + + {sortedDomains?.map((childDomain) => ( + + ))} + + + + ); +} diff --git a/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/useHasDomainChildren.ts b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/useHasDomainChildren.ts new file mode 100644 index 00000000000000..d16d5de23fbafc --- /dev/null +++ b/datahub-web-react/src/app/domain/nestedDomains/domainNavigator/useHasDomainChildren.ts @@ -0,0 +1,29 @@ +import { useEffect } from 'react'; +import { useGetDomainChildrenCountLazyQuery } from '../../../../graphql/domain.generated'; +import { useDomainsContext } from '../../DomainsContext'; + +interface Props { + domainUrn: string; + numDomainChildren: number; // number that comes from parent query to render this domain +} + +export default function useHasDomainChildren({ domainUrn, numDomainChildren }: Props) { + const { parentDomainsToUpdate, setParentDomainsToUpdate } = useDomainsContext(); + const [getDomainChildrenCount, { data: childrenData }] = useGetDomainChildrenCountLazyQuery(); + + useEffect(() => { + let timer; + // fetch updated children count to determine if we show triangle toggle + if (parentDomainsToUpdate.includes(domainUrn)) { + timer = setTimeout(() => { + getDomainChildrenCount({ variables: { urn: domainUrn } }); + setParentDomainsToUpdate(parentDomainsToUpdate.filter((urn) => urn !== domainUrn)); + }, 2000); + } + return () => { + if (timer) window.clearTimeout(timer); + }; + }, [domainUrn, getDomainChildrenCount, parentDomainsToUpdate, setParentDomainsToUpdate]); + + return childrenData ? !!childrenData.domain?.children?.total : !!numDomainChildren; +} diff --git a/datahub-web-react/src/app/domain/useListDomains.tsx b/datahub-web-react/src/app/domain/useListDomains.tsx new file mode 100644 index 00000000000000..74f6b454f11d4b --- /dev/null +++ b/datahub-web-react/src/app/domain/useListDomains.tsx @@ -0,0 +1,27 @@ +import { useListDomainsQuery } from '../../graphql/domain.generated'; +import { useSortedDomains } from './utils'; + +interface Props { + parentDomain?: string; + skip?: boolean; + sortBy?: 'displayName'; +} + +export default function useListDomains({ parentDomain, skip, sortBy = 'displayName' }: Props) { + const { data, error, loading, refetch } = useListDomainsQuery({ + skip, + variables: { + input: { + start: 0, + count: 1000, // don't paginate the home page, get all root level domains + parentDomain, + }, + }, + fetchPolicy: 'network-only', // always use network request first to populate cache + nextFetchPolicy: 'cache-first', // then use cache after that so we can manipulate it + }); + + const sortedDomains = useSortedDomains(data?.listDomains?.domains, sortBy); + + return { data, sortedDomains, error, loading, refetch }; +} diff --git a/datahub-web-react/src/app/domain/utils.ts b/datahub-web-react/src/app/domain/utils.ts index 3af161bc445659..8273c33e2c41df 100644 --- a/datahub-web-react/src/app/domain/utils.ts +++ b/datahub-web-react/src/app/domain/utils.ts @@ -1,9 +1,18 @@ +import { ApolloClient } from '@apollo/client'; +import { useEffect } from 'react'; +import { isEqual } from 'lodash'; import { ListDomainsDocument, ListDomainsQuery } from '../../graphql/domain.generated'; +import { Entity, EntityType } from '../../types.generated'; +import { GenericEntityProperties } from '../entity/shared/types'; +import usePrevious from '../shared/usePrevious'; +import { useDomainsContext } from './DomainsContext'; +import { useEntityRegistry } from '../useEntityRegistry'; +import EntityRegistry from '../entity/EntityRegistry'; /** * Add an entry to the list domains cache. */ -export const addToListDomainsCache = (client, newDomain, pageSize) => { +export const addToListDomainsCache = (client, newDomain, pageSize, parentDomain?: string) => { // Read the data from our cache for this query. const currData: ListDomainsQuery | null = client.readQuery({ query: ListDomainsDocument, @@ -11,6 +20,7 @@ export const addToListDomainsCache = (client, newDomain, pageSize) => { input: { start: 0, count: pageSize, + parentDomain, }, }, }); @@ -25,6 +35,7 @@ export const addToListDomainsCache = (client, newDomain, pageSize) => { input: { start: 0, count: pageSize, + parentDomain, }, }, data: { @@ -38,10 +49,39 @@ export const addToListDomainsCache = (client, newDomain, pageSize) => { }); }; +export const updateListDomainsCache = ( + client: ApolloClient, + urn: string, + id: string | undefined, + name: string, + description: string | undefined, + parentDomain?: string, +) => { + addToListDomainsCache( + client, + { + urn, + id: id || null, + type: EntityType.Domain, + properties: { + name, + description: description || null, + }, + ownership: null, + entities: null, + children: null, + dataProducts: null, + parentDomains: null, + }, + 1000, + parentDomain, + ); +}; + /** * Remove an entry from the list domains cache. */ -export const removeFromListDomainsCache = (client, urn, page, pageSize) => { +export const removeFromListDomainsCache = (client, urn, page, pageSize, parentDomain?: string) => { // Read the data from our cache for this query. const currData: ListDomainsQuery | null = client.readQuery({ query: ListDomainsDocument, @@ -49,6 +89,7 @@ export const removeFromListDomainsCache = (client, urn, page, pageSize) => { input: { start: (page - 1) * pageSize, count: pageSize, + parentDomain, }, }, }); @@ -63,6 +104,7 @@ export const removeFromListDomainsCache = (client, urn, page, pageSize) => { input: { start: (page - 1) * pageSize, count: pageSize, + parentDomain, }, }, data: { @@ -75,3 +117,29 @@ export const removeFromListDomainsCache = (client, urn, page, pageSize) => { }, }); }; + +export function useUpdateDomainEntityDataOnChange(entityData: GenericEntityProperties | null, entityType: EntityType) { + const { setEntityData } = useDomainsContext(); + const previousEntityData = usePrevious(entityData); + + useEffect(() => { + if (EntityType.Domain === entityType && !isEqual(entityData, previousEntityData)) { + setEntityData(entityData); + } + }); +} + +export function useSortedDomains(domains?: Array, sortBy?: 'displayName') { + const entityRegistry = useEntityRegistry(); + if (!domains || !sortBy) return domains; + return [...domains].sort((a, b) => { + const nameA = entityRegistry.getDisplayName(EntityType.Domain, a) || ''; + const nameB = entityRegistry.getDisplayName(EntityType.Domain, b) || ''; + return nameA.localeCompare(nameB); + }); +} + +export function getParentDomains(domain: T, entityRegistry: EntityRegistry) { + const props = entityRegistry.getGenericEntityProperties(EntityType.Domain, domain); + return props?.parentDomains?.domains ?? []; +} diff --git a/datahub-web-react/src/app/entity/Access/RoleEntity.tsx b/datahub-web-react/src/app/entity/Access/RoleEntity.tsx new file mode 100644 index 00000000000000..e63db9d0bbb2a4 --- /dev/null +++ b/datahub-web-react/src/app/entity/Access/RoleEntity.tsx @@ -0,0 +1,88 @@ +import { TagOutlined, TagFilled } from '@ant-design/icons'; +import * as React from 'react'; +import styled from 'styled-components'; +import { Role, EntityType, SearchResult } from '../../../types.generated'; +import DefaultPreviewCard from '../../preview/DefaultPreviewCard'; +import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '../Entity'; +import { getDataForEntityType } from '../shared/containers/profile/utils'; +import { urlEncodeUrn } from '../shared/utils'; +import RoleEntityProfile from './RoleEntityProfile'; + +const PreviewTagIcon = styled(TagOutlined)` + font-size: 20px; +`; +// /** +// * Definition of the DataHub Access Role entity. +// */ +export class RoleEntity implements Entity { + type: EntityType = EntityType.Role; + + icon = (fontSize: number, styleType: IconStyleType, color?: string) => { + if (styleType === IconStyleType.TAB_VIEW) { + return ; + } + + if (styleType === IconStyleType.HIGHLIGHT) { + return ; + } + + return ( + + ); + }; + + isSearchEnabled = () => true; + + isBrowseEnabled = () => false; + + isLineageEnabled = () => false; + + getAutoCompleteFieldName = () => 'name'; + + getPathName: () => string = () => 'role'; + + getCollectionName: () => string = () => 'Roles'; + + getEntityName: () => string = () => 'Role'; + + renderProfile: (urn: string) => JSX.Element = (_) => ; + + renderPreview = (_: PreviewType, data: Role) => ( + } + type="Role" + typeIcon={this.icon(14, IconStyleType.ACCENT)} + /> + ); + + renderSearch = (result: SearchResult) => { + return this.renderPreview(PreviewType.SEARCH, result.entity as Role); + }; + + displayName = (data: Role) => { + return data.properties?.name || data.urn; + }; + + getOverridePropertiesFromEntity = (data: Role) => { + return { + name: data.properties?.name, + }; + }; + + getGenericEntityProperties = (role: Role) => { + return getDataForEntityType({ data: role, entityType: this.type, getOverrideProperties: (data) => data }); + }; + + supportedCapabilities = () => { + return new Set([EntityCapabilityType.OWNERS]); + }; +} diff --git a/datahub-web-react/src/app/entity/Access/RoleEntityProfile.tsx b/datahub-web-react/src/app/entity/Access/RoleEntityProfile.tsx new file mode 100644 index 00000000000000..d8a31700fb918e --- /dev/null +++ b/datahub-web-react/src/app/entity/Access/RoleEntityProfile.tsx @@ -0,0 +1,75 @@ +import React from 'react'; + +import { useParams } from 'react-router'; +import { Divider, Typography } from 'antd'; +import { grey } from '@ant-design/colors'; +import styled from 'styled-components'; + +import { Message } from '../../shared/Message'; +import { decodeUrn } from '../shared/utils'; +import { useGetExternalRoleQuery } from '../../../graphql/accessrole.generated'; + +const PageContainer = styled.div` + padding: 32px 100px; +`; + +const LoadingMessage = styled(Message)` + margin-top: 10%; +`; + +type RolePageParams = { + urn: string; +}; + +const TitleLabel = styled(Typography.Text)` + &&& { + color: ${grey[2]}; + font-size: 12px; + display: block; + line-height: 20px; + font-weight: 700; + } +`; + +const DescriptionLabel = styled(Typography.Text)` + &&& { + text-align: left; + font-weight: bold; + font-size: 14px; + line-height: 28px; + color: rgb(38, 38, 38); + } +`; + +const TitleText = styled(Typography.Text)` + &&& { + color: ${grey[10]}; + font-weight: 700; + font-size: 20px; + line-height: 28px; + display: inline-block; + margin: 0px 7px; + } +`; + +const { Paragraph } = Typography; + +export default function RoleEntityProfile() { + const { urn: encodedUrn } = useParams(); + const urn = decodeUrn(encodedUrn); + const { data, loading } = useGetExternalRoleQuery({ variables: { urn } }); + + return ( + + {loading && } + Role + {data?.role?.properties?.name} + + {/* Role Description */} + About + + {data?.role?.properties?.description} + + + ); +} diff --git a/datahub-web-react/src/app/entity/EntityRegistry.tsx b/datahub-web-react/src/app/entity/EntityRegistry.tsx index a07fd02841197c..6642c2c7b0467c 100644 --- a/datahub-web-react/src/app/entity/EntityRegistry.tsx +++ b/datahub-web-react/src/app/entity/EntityRegistry.tsx @@ -1,5 +1,7 @@ +import React from 'react'; import { Entity as EntityInterface, EntityType, SearchResult } from '../../types.generated'; import { FetchedEntity } from '../lineage/types'; +import { SearchResultProvider } from '../search/context/SearchResultContext'; import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from './Entity'; import { GLOSSARY_ENTITY_TYPES } from './shared/constants'; import { GenericEntityProperties } from './shared/types'; @@ -43,6 +45,12 @@ export default class EntityRegistry { return this.entities; } + getEntitiesForSearchRoutes(): Array> { + return this.entities.filter( + (entity) => !GLOSSARY_ENTITY_TYPES.includes(entity.type) && entity.type !== EntityType.Domain, + ); + } + getNonGlossaryEntities(): Array> { return this.entities.filter((entity) => !GLOSSARY_ENTITY_TYPES.includes(entity.type)); } @@ -119,7 +127,9 @@ export default class EntityRegistry { renderSearchResult(type: EntityType, searchResult: SearchResult): JSX.Element { const entity = validatedGet(type, this.entityTypeToEntity); - return entity.renderSearch(searchResult); + return ( + {entity.renderSearch(searchResult)} + ); } renderBrowse(type: EntityType, data: T): JSX.Element { diff --git a/datahub-web-react/src/app/entity/chart/ChartEntity.tsx b/datahub-web-react/src/app/entity/chart/ChartEntity.tsx index b5ebcbef803792..0f1b6dbf3d660d 100644 --- a/datahub-web-react/src/app/entity/chart/ChartEntity.tsx +++ b/datahub-web-react/src/app/entity/chart/ChartEntity.tsx @@ -19,13 +19,14 @@ import { EntityMenuItems } from '../shared/EntityDropdown/EntityDropdown'; import { LineageTab } from '../shared/tabs/Lineage/LineageTab'; import { ChartStatsSummarySubHeader } from './profile/stats/ChartStatsSummarySubHeader'; import { InputFieldsTab } from '../shared/tabs/Entity/InputFieldsTab'; -import { ChartSnippet } from './ChartSnippet'; import { EmbedTab } from '../shared/tabs/Embed/EmbedTab'; import { capitalizeFirstLetterOnly } from '../../shared/textUtil'; import DataProductSection from '../shared/containers/profile/sidebar/DataProduct/DataProductSection'; import { getDataProduct } from '../shared/utils'; import EmbeddedProfile from '../shared/embed/EmbeddedProfile'; import { LOOKER_URN } from '../../ingest/source/builder/constants'; +import { MatchedFieldList } from '../../search/matches/MatchedFieldList'; +import { matchedInputFieldRenderer } from '../../search/matches/matchedInputFieldRenderer'; /** * Definition of the DataHub Chart entity. @@ -203,7 +204,11 @@ export class ChartEntity implements Entity { lastUpdatedMs={data.properties?.lastModified?.time} createdMs={data.properties?.created?.time} externalUrl={data.properties?.externalUrl} - snippet={} + snippet={ + matchedInputFieldRenderer(matchedField, data)} + /> + } degree={(result as any).degree} paths={(result as any).paths} /> diff --git a/datahub-web-react/src/app/entity/chart/ChartSnippet.tsx b/datahub-web-react/src/app/entity/chart/ChartSnippet.tsx deleted file mode 100644 index 27982d3037207a..00000000000000 --- a/datahub-web-react/src/app/entity/chart/ChartSnippet.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; - -import { Typography } from 'antd'; -import { InputFields, MatchedField, Maybe } from '../../../types.generated'; -import TagTermGroup from '../../shared/tags/TagTermGroup'; -import { FIELDS_TO_HIGHLIGHT } from '../dataset/search/highlights'; -import { getMatchPrioritizingPrimary } from '../shared/utils'; - -type Props = { - matchedFields: MatchedField[]; - inputFields: Maybe | undefined; - isMatchingDashboard?: boolean; -}; - -const LABEL_INDEX_NAME = 'fieldLabels'; -const TYPE_PROPERTY_KEY_NAME = 'type'; - -export const ChartSnippet = ({ matchedFields, inputFields, isMatchingDashboard = false }: Props) => { - const matchedField = getMatchPrioritizingPrimary(matchedFields, 'fieldLabels'); - - if (matchedField?.name === LABEL_INDEX_NAME) { - const matchedSchemaField = inputFields?.fields?.find( - (field) => field?.schemaField?.label === matchedField.value, - ); - const matchedGlossaryTerm = matchedSchemaField?.schemaField?.glossaryTerms?.terms?.find( - (term) => term?.term?.name === matchedField.value, - ); - - if (matchedGlossaryTerm) { - let termType = 'term'; - const typeProperty = matchedGlossaryTerm.term.properties?.customProperties?.find( - (property) => property.key === TYPE_PROPERTY_KEY_NAME, - ); - if (typeProperty) { - termType = typeProperty.value || termType; - } - - return ( - - Matches {termType} {' '} - {isMatchingDashboard && 'on a contained Chart'} - - ); - } - } - - return matchedField ? ( - - Matches {FIELDS_TO_HIGHLIGHT.get(matchedField.name)} {matchedField.value}{' '} - {isMatchingDashboard && 'on a contained Chart'} - - ) : null; -}; diff --git a/datahub-web-react/src/app/entity/dashboard/DashboardEntity.tsx b/datahub-web-react/src/app/entity/dashboard/DashboardEntity.tsx index a64e4372652620..0a36d0e5f1bfad 100644 --- a/datahub-web-react/src/app/entity/dashboard/DashboardEntity.tsx +++ b/datahub-web-react/src/app/entity/dashboard/DashboardEntity.tsx @@ -24,12 +24,13 @@ import { EntityMenuItems } from '../shared/EntityDropdown/EntityDropdown'; import { LineageTab } from '../shared/tabs/Lineage/LineageTab'; import { capitalizeFirstLetterOnly } from '../../shared/textUtil'; import { DashboardStatsSummarySubHeader } from './profile/DashboardStatsSummarySubHeader'; -import { ChartSnippet } from '../chart/ChartSnippet'; import { EmbedTab } from '../shared/tabs/Embed/EmbedTab'; import EmbeddedProfile from '../shared/embed/EmbeddedProfile'; import DataProductSection from '../shared/containers/profile/sidebar/DataProduct/DataProductSection'; import { getDataProduct } from '../shared/utils'; import { LOOKER_URN } from '../../ingest/source/builder/constants'; +import { MatchedFieldList } from '../../search/matches/MatchedFieldList'; +import { matchedInputFieldRenderer } from '../../search/matches/matchedInputFieldRenderer'; /** * Definition of the DataHub Dashboard entity. @@ -227,10 +228,9 @@ export class DashboardEntity implements Entity { lastUpdatedMs={data.properties?.lastModified?.time} createdMs={data.properties?.created?.time} snippet={ - matchedInputFieldRenderer(matchedField, data)} + matchSuffix="on a contained chart" /> } subtype={data.subTypes?.typeNames?.[0]} diff --git a/datahub-web-react/src/app/entity/dataset/DatasetEntity.tsx b/datahub-web-react/src/app/entity/dataset/DatasetEntity.tsx index cb4239872045f6..7d40b97a66b3b6 100644 --- a/datahub-web-react/src/app/entity/dataset/DatasetEntity.tsx +++ b/datahub-web-react/src/app/entity/dataset/DatasetEntity.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { DatabaseFilled, DatabaseOutlined } from '@ant-design/icons'; import { Dataset, DatasetProperties, EntityType, OwnershipType, SearchResult } from '../../../types.generated'; import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '../Entity'; +import { useAppConfig } from '../../useAppConfig'; import { Preview } from './preview/Preview'; import { EntityProfile } from '../shared/containers/profile/EntityProfile'; import { GetDatasetQuery, useGetDatasetQuery, useUpdateDatasetMutation } from '../../../graphql/dataset.generated'; @@ -25,11 +26,13 @@ import { OperationsTab } from './profile/OperationsTab'; import { EntityMenuItems } from '../shared/EntityDropdown/EntityDropdown'; import { SidebarSiblingsSection } from '../shared/containers/profile/sidebar/SidebarSiblingsSection'; import { DatasetStatsSummarySubHeader } from './profile/stats/stats/DatasetStatsSummarySubHeader'; -import { DatasetSearchSnippet } from './DatasetSearchSnippet'; +import { MatchedFieldList } from '../../search/matches/MatchedFieldList'; import { EmbedTab } from '../shared/tabs/Embed/EmbedTab'; import EmbeddedProfile from '../shared/embed/EmbeddedProfile'; import DataProductSection from '../shared/containers/profile/sidebar/DataProduct/DataProductSection'; import { getDataProduct } from '../shared/utils'; +import AccessManagement from '../shared/tabs/Dataset/AccessManagement/AccessManagement'; +import { matchedFieldPathsRenderer } from '../../search/matches/matchedFieldPathsRenderer'; const SUBTYPES = { VIEW: 'view', @@ -68,6 +71,8 @@ export class DatasetEntity implements Entity { isSearchEnabled = () => true; + appconfig = useAppConfig; + isBrowseEnabled = () => true; isLineageEnabled = () => true; @@ -175,6 +180,14 @@ export class DatasetEntity implements Entity { }, }, }, + { + name: 'Access Management', + component: AccessManagement, + display: { + visible: (_, _1) => this.appconfig().config.featureFlags.showAccessManagement, + enabled: (_, _2) => true, + }, + }, ]} sidebarSections={[ { @@ -290,7 +303,7 @@ export class DatasetEntity implements Entity { subtype={data.subTypes?.typeNames?.[0]} container={data.container} parentContainers={data.parentContainers} - snippet={} + snippet={} insights={result.insights} externalUrl={data.properties?.externalUrl} statsSummary={data.statsSummary} @@ -316,6 +329,7 @@ export class DatasetEntity implements Entity { subtype: entity?.subTypes?.typeNames?.[0] || undefined, icon: entity?.platform?.properties?.logoUrl || undefined, platform: entity?.platform, + health: entity?.health || undefined, }; }; diff --git a/datahub-web-react/src/app/entity/dataset/DatasetSearchSnippet.tsx b/datahub-web-react/src/app/entity/dataset/DatasetSearchSnippet.tsx deleted file mode 100644 index e4f88eb0fbbfa2..00000000000000 --- a/datahub-web-react/src/app/entity/dataset/DatasetSearchSnippet.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; - -import { Typography } from 'antd'; -import { MatchedField } from '../../../types.generated'; -import { TagSummary } from './shared/TagSummary'; -import { TermSummary } from './shared/TermSummary'; -import { FIELDS_TO_HIGHLIGHT } from './search/highlights'; -import { getMatchPrioritizingPrimary } from '../shared/utils'; -import { downgradeV2FieldPath } from './profile/schema/utils/utils'; - -type Props = { - matchedFields: MatchedField[]; -}; - -const LABEL_INDEX_NAME = 'fieldLabels'; - -export const DatasetSearchSnippet = ({ matchedFields }: Props) => { - const matchedField = getMatchPrioritizingPrimary(matchedFields, LABEL_INDEX_NAME); - - let snippet: React.ReactNode; - - if (matchedField) { - if (matchedField.value.includes('urn:li:tag')) { - snippet = ; - } else if (matchedField.value.includes('urn:li:glossaryTerm')) { - snippet = ; - } else if (matchedField.name === 'fieldPaths') { - snippet = {downgradeV2FieldPath(matchedField.value)}; - } else { - snippet = {matchedField.value}; - } - } - - return matchedField ? ( - - Matches {FIELDS_TO_HIGHLIGHT.get(matchedField.name)} {snippet}{' '} - - ) : null; -}; diff --git a/datahub-web-react/src/app/entity/dataset/search/highlights.ts b/datahub-web-react/src/app/entity/dataset/search/highlights.ts deleted file mode 100644 index 64505e0709c7ba..00000000000000 --- a/datahub-web-react/src/app/entity/dataset/search/highlights.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const FIELDS_TO_HIGHLIGHT = new Map(); -FIELDS_TO_HIGHLIGHT.set('fieldPaths', 'column'); -FIELDS_TO_HIGHLIGHT.set('fieldDescriptions', 'column description'); -FIELDS_TO_HIGHLIGHT.set('fieldTags', 'column tag'); -FIELDS_TO_HIGHLIGHT.set('editedFieldDescriptions', 'column description'); -FIELDS_TO_HIGHLIGHT.set('editedFieldTags', 'column tag'); -FIELDS_TO_HIGHLIGHT.set('fieldLabels', 'label'); diff --git a/datahub-web-react/src/app/entity/dataset/shared/TagSummary.tsx b/datahub-web-react/src/app/entity/dataset/shared/TagSummary.tsx deleted file mode 100644 index 106cc298fb58c4..00000000000000 --- a/datahub-web-react/src/app/entity/dataset/shared/TagSummary.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; -import { useGetTagQuery } from '../../../../graphql/tag.generated'; -import { EntityType, Tag } from '../../../../types.generated'; -import { HoverEntityTooltip } from '../../../recommendations/renderer/component/HoverEntityTooltip'; -import { useEntityRegistry } from '../../../useEntityRegistry'; -import { StyledTag } from '../../shared/components/styled/StyledTag'; - -const TagLink = styled.span` - display: inline-block; -`; - -type Props = { - urn: string; -}; - -export const TagSummary = ({ urn }: Props) => { - const entityRegistry = useEntityRegistry(); - const { data } = useGetTagQuery({ variables: { urn } }); - return ( - <> - {data && ( - - - - {entityRegistry.getDisplayName(EntityType.Tag, data?.tag)} - - - - )} - - ); -}; diff --git a/datahub-web-react/src/app/entity/dataset/shared/TermSummary.tsx b/datahub-web-react/src/app/entity/dataset/shared/TermSummary.tsx deleted file mode 100644 index cc1274693a3420..00000000000000 --- a/datahub-web-react/src/app/entity/dataset/shared/TermSummary.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { Tag } from 'antd'; -import { BookOutlined } from '@ant-design/icons'; -import styled from 'styled-components'; -import { useGetGlossaryTermQuery } from '../../../../graphql/glossaryTerm.generated'; -import { HoverEntityTooltip } from '../../../recommendations/renderer/component/HoverEntityTooltip'; -import { EntityType, GlossaryTerm } from '../../../../types.generated'; -import { useEntityRegistry } from '../../../useEntityRegistry'; - -const TermLink = styled.span` - display: inline-block; -`; - -type Props = { - urn: string; -}; - -export const TermSummary = ({ urn }: Props) => { - const entityRegistry = useEntityRegistry(); - const { data } = useGetGlossaryTermQuery({ variables: { urn } }); - - return ( - <> - {data && ( - - - - - {entityRegistry.getDisplayName(EntityType.GlossaryTerm, data?.glossaryTerm)} - - - - )} - - ); -}; diff --git a/datahub-web-react/src/app/entity/domain/DomainEntity.tsx b/datahub-web-react/src/app/entity/domain/DomainEntity.tsx index 3b3045abe2a7c2..68c06935dbbe57 100644 --- a/datahub-web-react/src/app/entity/domain/DomainEntity.tsx +++ b/datahub-web-react/src/app/entity/domain/DomainEntity.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { FolderOutlined } from '@ant-design/icons'; import { Domain, EntityType, SearchResult } from '../../../types.generated'; import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '../Entity'; import { Preview } from './preview/Preview'; @@ -14,7 +13,7 @@ import { EntityMenuItems } from '../shared/EntityDropdown/EntityDropdown'; import { EntityActionItem } from '../shared/entity/EntityActions'; import DataProductsTab from './DataProductsTab/DataProductsTab'; import { EntityProfileTab } from '../shared/constants'; -// import { EntityActionItem } from '../shared/entity/EntityActions'; +import DomainIcon from '../../domain/DomainIcon'; /** * Definition of the DataHub Domain entity. @@ -24,21 +23,26 @@ export class DomainEntity implements Entity { icon = (fontSize: number, styleType: IconStyleType, color?: string) => { if (styleType === IconStyleType.TAB_VIEW) { - return ; + return ; } if (styleType === IconStyleType.HIGHLIGHT) { - return ; + return ; } if (styleType === IconStyleType.SVG) { return ( - + ); } return ( - { useEntityQuery={useGetDomainQuery} useUpdateQuery={undefined} getOverrideProperties={this.getOverridePropertiesFromEntity} - headerDropdownItems={new Set([EntityMenuItems.DELETE])} + headerDropdownItems={new Set([EntityMenuItems.MOVE, EntityMenuItems.DELETE])} headerActionItems={new Set([EntityActionItem.BATCH_ADD_DOMAIN])} isNameEditable tabs={[ @@ -102,11 +106,11 @@ export class DomainEntity implements Entity { renderPreview = (_: PreviewType, data: Domain) => { return ( ); @@ -116,11 +120,11 @@ export class DomainEntity implements Entity { const data = result.entity as Domain; return ( ); diff --git a/datahub-web-react/src/app/entity/domain/preview/DomainEntitiesSnippet.tsx b/datahub-web-react/src/app/entity/domain/preview/DomainEntitiesSnippet.tsx new file mode 100644 index 00000000000000..6d36964004d64f --- /dev/null +++ b/datahub-web-react/src/app/entity/domain/preview/DomainEntitiesSnippet.tsx @@ -0,0 +1,45 @@ +import { DatabaseOutlined, FileDoneOutlined } from '@ant-design/icons'; +import { VerticalDivider } from '@remirror/react'; +import React from 'react'; +import styled from 'styled-components'; +import { SearchResultFields_Domain_Fragment } from '../../../../graphql/search.generated'; +import { ANTD_GRAY_V2 } from '../../shared/constants'; +import DomainIcon from '../../../domain/DomainIcon'; +import { pluralize } from '../../../shared/textUtil'; + +const Wrapper = styled.div` + color: ${ANTD_GRAY_V2[8]}; + font-size: 12px; + display: flex; + align-items: center; + + svg { + margin-right: 4px; + } +`; + +const StyledDivider = styled(VerticalDivider)` + &&& { + margin: 0 8px; + } +`; + +interface Props { + domain: SearchResultFields_Domain_Fragment; +} + +export default function DomainEntitiesSnippet({ domain }: Props) { + const entityCount = domain.entities?.total || 0; + const subDomainCount = domain.children?.total || 0; + const dataProductCount = domain.dataProducts?.total || 0; + + return ( + + {entityCount} {entityCount === 1 ? 'entity' : 'entities'} + + {subDomainCount} {pluralize(subDomainCount, 'sub-domain')} + + {dataProductCount} {pluralize(dataProductCount, 'data product')} + + ); +} diff --git a/datahub-web-react/src/app/entity/domain/preview/Preview.tsx b/datahub-web-react/src/app/entity/domain/preview/Preview.tsx index 18cb2bb75df031..83198f6eba2d88 100644 --- a/datahub-web-react/src/app/entity/domain/preview/Preview.tsx +++ b/datahub-web-react/src/app/entity/domain/preview/Preview.tsx @@ -1,23 +1,24 @@ import React from 'react'; -import { EntityType, Owner, SearchInsight } from '../../../../types.generated'; +import { Domain, EntityType, Owner, SearchInsight } from '../../../../types.generated'; import DefaultPreviewCard from '../../../preview/DefaultPreviewCard'; import { useEntityRegistry } from '../../../useEntityRegistry'; -import { IconStyleType } from '../../Entity'; +import DomainEntitiesSnippet from './DomainEntitiesSnippet'; +import DomainIcon from '../../../domain/DomainIcon'; export const Preview = ({ + domain, urn, name, description, owners, - count, insights, logoComponent, }: { + domain: Domain; urn: string; name: string; description?: string | null; owners?: Array | null; - count?: number | null; insights?: Array | null; logoComponent?: JSX.Element; }): JSX.Element => { @@ -29,11 +30,19 @@ export const Preview = ({ urn={urn} description={description || ''} type="Domain" - typeIcon={entityRegistry.getIcon(EntityType.Domain, 14, IconStyleType.ACCENT)} + typeIcon={ + + } owners={owners} insights={insights} logoComponent={logoComponent} - entityCount={count || undefined} + parentEntities={domain.parentDomains?.domains} + snippet={} /> ); }; diff --git a/datahub-web-react/src/app/entity/glossaryNode/preview/Preview.tsx b/datahub-web-react/src/app/entity/glossaryNode/preview/Preview.tsx index 6c6ea163c6786d..3938049059e4db 100644 --- a/datahub-web-react/src/app/entity/glossaryNode/preview/Preview.tsx +++ b/datahub-web-react/src/app/entity/glossaryNode/preview/Preview.tsx @@ -27,7 +27,7 @@ export const Preview = ({ owners={owners} logoComponent={} type={entityRegistry.getEntityName(EntityType.GlossaryNode)} - parentNodes={parentNodes} + parentEntities={parentNodes?.nodes} /> ); }; diff --git a/datahub-web-react/src/app/entity/glossaryTerm/preview/Preview.tsx b/datahub-web-react/src/app/entity/glossaryTerm/preview/Preview.tsx index 26d3cf456ab7a6..ee87633cb6fa9e 100644 --- a/datahub-web-react/src/app/entity/glossaryTerm/preview/Preview.tsx +++ b/datahub-web-react/src/app/entity/glossaryTerm/preview/Preview.tsx @@ -4,6 +4,8 @@ import { Deprecation, Domain, EntityType, Owner, ParentNodesResult } from '../.. import DefaultPreviewCard from '../../../preview/DefaultPreviewCard'; import { useEntityRegistry } from '../../../useEntityRegistry'; import { IconStyleType, PreviewType } from '../../Entity'; +import UrlButton from '../../shared/UrlButton'; +import { getRelatedEntitiesUrl } from '../utils'; export const Preview = ({ urn, @@ -37,8 +39,11 @@ export const Preview = ({ type="Glossary Term" typeIcon={entityRegistry.getIcon(EntityType.GlossaryTerm, 14, IconStyleType.ACCENT)} deprecation={deprecation} - parentNodes={parentNodes} + parentEntities={parentNodes?.nodes} domain={domain} + entityTitleSuffix={ + View Related Entities + } /> ); }; diff --git a/datahub-web-react/src/app/entity/glossaryTerm/profile/GlossaryRelatedEntity.tsx b/datahub-web-react/src/app/entity/glossaryTerm/profile/GlossaryRelatedEntity.tsx index d0e8de0928b487..098e97e526fd84 100644 --- a/datahub-web-react/src/app/entity/glossaryTerm/profile/GlossaryRelatedEntity.tsx +++ b/datahub-web-react/src/app/entity/glossaryTerm/profile/GlossaryRelatedEntity.tsx @@ -5,7 +5,7 @@ import { EmbeddedListSearchSection } from '../../shared/components/styled/search import { useEntityData } from '../../shared/EntityContext'; export default function GlossaryRelatedEntity() { - const { entityData }: any = useEntityData(); + const { entityData } = useEntityData(); const entityUrn = entityData?.urn; diff --git a/datahub-web-react/src/app/entity/glossaryTerm/utils.ts b/datahub-web-react/src/app/entity/glossaryTerm/utils.ts index 3a2a3d35a8126f..cbfa76fa348663 100644 --- a/datahub-web-react/src/app/entity/glossaryTerm/utils.ts +++ b/datahub-web-react/src/app/entity/glossaryTerm/utils.ts @@ -6,3 +6,7 @@ export function sortGlossaryTerms(entityRegistry: EntityRegistry, nodeA?: Entity const nodeBName = entityRegistry.getDisplayName(EntityType.GlossaryTerm, nodeB) || ''; return nodeAName.localeCompare(nodeBName); } + +export function getRelatedEntitiesUrl(entityRegistry: EntityRegistry, urn: string) { + return `${entityRegistry.getEntityUrl(EntityType.GlossaryTerm, urn)}/${encodeURIComponent('Related Entities')}`; +} diff --git a/datahub-web-react/src/app/entity/group/preview/Preview.tsx b/datahub-web-react/src/app/entity/group/preview/Preview.tsx index dc83f6fe4f840f..5b9a25e198cfe2 100644 --- a/datahub-web-react/src/app/entity/group/preview/Preview.tsx +++ b/datahub-web-react/src/app/entity/group/preview/Preview.tsx @@ -8,6 +8,7 @@ import { useEntityRegistry } from '../../../useEntityRegistry'; import { ANTD_GRAY } from '../../shared/constants'; import { IconStyleType } from '../../Entity'; import NoMarkdownViewer from '../../shared/components/styled/StripMarkdownText'; +import SearchTextHighlighter from '../../../search/matches/SearchTextHighlighter'; const PreviewContainer = styled.div` margin-bottom: 4px; @@ -87,7 +88,7 @@ export const Preview = ({ {entityRegistry.getEntityName(EntityType.CorpGroup)} - {name || urn} + {name ? : urn} {membersCount} members @@ -96,7 +97,12 @@ export const Preview = ({ {description && description.length > 0 && ( - {description} + } + > + {description} + )} diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/DomainParentSelect.tsx b/datahub-web-react/src/app/entity/shared/EntityDropdown/DomainParentSelect.tsx new file mode 100644 index 00000000000000..d43b04ec11a165 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/DomainParentSelect.tsx @@ -0,0 +1,108 @@ +import React, { MouseEvent } from 'react'; +import { Select } from 'antd'; +import { CloseCircleFilled } from '@ant-design/icons'; +import styled from 'styled-components'; +import { Domain, EntityType } from '../../../../types.generated'; +import { useEntityRegistry } from '../../../useEntityRegistry'; +import ClickOutside from '../../../shared/ClickOutside'; +import { BrowserWrapper } from '../../../shared/tags/AddTagsTermsModal'; +import useParentSelector from './useParentSelector'; +import DomainNavigator from '../../../domain/nestedDomains/domainNavigator/DomainNavigator'; +import { useDomainsContext } from '../../../domain/DomainsContext'; +import ParentEntities from '../../../search/filters/ParentEntities'; +import { getParentDomains } from '../../../domain/utils'; + +const SearchResultContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; +`; + +// filter out entity itself and its children +export function filterResultsForMove(entity: Domain, entityUrn: string) { + return ( + entity.urn !== entityUrn && + entity.__typename === 'Domain' && + !entity.parentDomains?.domains.some((node) => node.urn === entityUrn) + ); +} + +interface Props { + selectedParentUrn: string; + setSelectedParentUrn: (parent: string) => void; + isMoving?: boolean; +} + +export default function DomainParentSelect({ selectedParentUrn, setSelectedParentUrn, isMoving }: Props) { + const entityRegistry = useEntityRegistry(); + const { entityData } = useDomainsContext(); + const domainUrn = entityData?.urn; + + const { + searchResults, + searchQuery, + isFocusedOnInput, + selectedParentName, + selectParentFromBrowser, + onSelectParent, + handleSearch, + clearSelectedParent, + setIsFocusedOnInput, + } = useParentSelector({ + entityType: EntityType.Domain, + entityData, + selectedParentUrn, + setSelectedParentUrn, + }); + const domainSearchResultsFiltered = + isMoving && domainUrn + ? searchResults.filter((r) => filterResultsForMove(r.entity as Domain, domainUrn)) + : searchResults; + + function selectDomain(domain: Domain) { + selectParentFromBrowser(domain.urn, entityRegistry.getDisplayName(EntityType.Domain, domain)); + } + + const isShowingDomainNavigator = !searchQuery && isFocusedOnInput; + + const handleFocus = () => setIsFocusedOnInput(true); + const handleClickOutside = () => setIsFocusedOnInput(false); + + const handleClear = (event: MouseEvent) => { + // Prevent, otherwise antd will close the select menu but leaves it focused + event.stopPropagation(); + clearSelectedParent(); + }; + + return ( + + + + + + + ); +} diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/EntityDropdown.tsx b/datahub-web-react/src/app/entity/shared/EntityDropdown/EntityDropdown.tsx index 3442c57ba2d611..be975249b26707 100644 --- a/datahub-web-react/src/app/entity/shared/EntityDropdown/EntityDropdown.tsx +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/EntityDropdown.tsx @@ -20,7 +20,10 @@ import { ANTD_GRAY } from '../constants'; import { useEntityRegistry } from '../../../useEntityRegistry'; import useDeleteEntity from './useDeleteEntity'; import { getEntityProfileDeleteRedirectPath } from '../../../shared/deleteUtils'; -import { isDeleteDisabled } from './utils'; +import { shouldDisplayChildDeletionWarning, isDeleteDisabled, isMoveDisabled } from './utils'; +import { useUserContext } from '../../../context/useUserContext'; +import MoveDomainModal from './MoveDomainModal'; +import { useIsNestedDomainsEnabled } from '../../../useAppConfig'; export enum EntityMenuItems { COPY_URL, @@ -89,8 +92,10 @@ function EntityDropdown(props: Props) { options, } = props; + const me = useUserContext(); const entityRegistry = useEntityRegistry(); const [updateDeprecation] = useUpdateDeprecationMutation(); + const isNestedDomainsEnabled = useIsNestedDomainsEnabled(); const { onDeleteEntity, hasBeenDeleted } = useDeleteEntity( urn, entityType, @@ -131,9 +136,9 @@ function EntityDropdown(props: Props) { const pageUrl = window.location.href; const isGlossaryEntity = entityType === EntityType.GlossaryNode || entityType === EntityType.GlossaryTerm; - const entityHasChildren = !!entityData?.children?.total; - const canManageGlossaryEntity = !!entityData?.privileges?.canManageEntity; + const isDomainEntity = entityType === EntityType.Domain; const canCreateGlossaryEntity = !!entityData?.privileges?.canManageChildren; + const isDomainMoveHidden = !isNestedDomainsEnabled && isDomainEntity; /** * A default path to redirect to if the entity is deleted. @@ -192,10 +197,10 @@ function EntityDropdown(props: Props) { )} - {menuItems.has(EntityMenuItems.MOVE) && ( + {!isDomainMoveHidden && menuItems.has(EntityMenuItems.MOVE) && ( setIsMoveModalVisible(true)} > @@ -206,17 +211,16 @@ function EntityDropdown(props: Props) { {menuItems.has(EntityMenuItems.DELETE) && ( @@ -252,7 +256,10 @@ function EntityDropdown(props: Props) { refetch={refetchForEntity} /> )} - {isMoveModalVisible && setIsMoveModalVisible(false)} />} + {isMoveModalVisible && isGlossaryEntity && ( + setIsMoveModalVisible(false)} /> + )} + {isMoveModalVisible && isDomainEntity && setIsMoveModalVisible(false)} />} {hasBeenDeleted && !onDelete && deleteRedirectPath && } ); diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/MoveDomainModal.tsx b/datahub-web-react/src/app/entity/shared/EntityDropdown/MoveDomainModal.tsx new file mode 100644 index 00000000000000..cdbf6fdabf3c99 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/MoveDomainModal.tsx @@ -0,0 +1,102 @@ +import React, { useState } from 'react'; +import styled from 'styled-components/macro'; +import { message, Button, Modal, Typography, Form } from 'antd'; +import { useRefetch } from '../EntityContext'; +import { useEntityRegistry } from '../../../useEntityRegistry'; +import { useMoveDomainMutation } from '../../../../graphql/domain.generated'; +import DomainParentSelect from './DomainParentSelect'; +import { useHandleMoveDomainComplete } from './useHandleMoveDomainComplete'; +import { useDomainsContext } from '../../../domain/DomainsContext'; +import { EntityType } from '../../../../types.generated'; + +const StyledItem = styled(Form.Item)` + margin-bottom: 0; +`; + +const OptionalWrapper = styled.span` + font-weight: normal; +`; + +interface Props { + onClose: () => void; +} + +function MoveDomainModal(props: Props) { + const { onClose } = props; + const { entityData } = useDomainsContext(); + const domainUrn = entityData?.urn; + const [form] = Form.useForm(); + const entityRegistry = useEntityRegistry(); + const [selectedParentUrn, setSelectedParentUrn] = useState(''); + const refetch = useRefetch(); + + const [moveDomainMutation] = useMoveDomainMutation(); + + const { handleMoveDomainComplete } = useHandleMoveDomainComplete(); + + function moveDomain() { + if (!domainUrn) return; + + moveDomainMutation({ + variables: { + input: { + resourceUrn: domainUrn, + parentDomain: selectedParentUrn || undefined, + }, + }, + }) + .then(() => { + message.loading({ content: 'Updating...', duration: 2 }); + const newParentToUpdate = selectedParentUrn || undefined; + handleMoveDomainComplete(domainUrn, newParentToUpdate); + setTimeout(() => { + message.success({ + content: `Moved ${entityRegistry.getEntityName(EntityType.Domain)}!`, + duration: 2, + }); + refetch(); + }, 2000); + }) + .catch((e) => { + message.destroy(); + message.error({ content: `Failed to move: \n ${e.message || ''}`, duration: 3 }); + }); + onClose(); + } + + return ( + + + + + } + > +
+ + Move To (optional) + + } + > + + + + +
+
+ ); +} + +export default MoveDomainModal; diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/NodeParentSelect.tsx b/datahub-web-react/src/app/entity/shared/EntityDropdown/NodeParentSelect.tsx index 86c2b84a67c3d1..c3bfac35c2ca6d 100644 --- a/datahub-web-react/src/app/entity/shared/EntityDropdown/NodeParentSelect.tsx +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/NodeParentSelect.tsx @@ -1,12 +1,12 @@ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { Select } from 'antd'; -import { useGetSearchResultsLazyQuery } from '../../../../graphql/search.generated'; -import { EntityType, GlossaryNode } from '../../../../types.generated'; +import { EntityType, GlossaryNode, SearchResult } from '../../../../types.generated'; import { useEntityRegistry } from '../../../useEntityRegistry'; import { useEntityData } from '../EntityContext'; import ClickOutside from '../../../shared/ClickOutside'; import GlossaryBrowser from '../../../glossary/GlossaryBrowser/GlossaryBrowser'; import { BrowserWrapper } from '../../../shared/tags/AddTagsTermsModal'; +import useParentSelector from './useParentSelector'; // filter out entity itself and its children export function filterResultsForMove(entity: GlossaryNode, entityUrn: string) { @@ -25,60 +25,29 @@ interface Props { function NodeParentSelect(props: Props) { const { selectedParentUrn, setSelectedParentUrn, isMoving } = props; - const [selectedParentName, setSelectedParentName] = useState(''); - const [isFocusedOnInput, setIsFocusedOnInput] = useState(false); - const [searchQuery, setSearchQuery] = useState(''); const entityRegistry = useEntityRegistry(); const { entityData, urn: entityDataUrn, entityType } = useEntityData(); - const [nodeSearch, { data: nodeData }] = useGetSearchResultsLazyQuery(); - let nodeSearchResults = nodeData?.search?.searchResults || []; - if (isMoving) { - nodeSearchResults = nodeSearchResults.filter((r) => - filterResultsForMove(r.entity as GlossaryNode, entityDataUrn), - ); - } - - useEffect(() => { - if (entityData && selectedParentUrn === entityDataUrn) { - const displayName = entityRegistry.getDisplayName(EntityType.GlossaryNode, entityData); - setSelectedParentName(displayName); - } - }, [entityData, entityRegistry, selectedParentUrn, entityDataUrn]); - - function handleSearch(text: string) { - setSearchQuery(text); - nodeSearch({ - variables: { - input: { - type: EntityType.GlossaryNode, - query: text, - start: 0, - count: 5, - }, - }, - }); - } + const { + searchResults, + searchQuery, + isFocusedOnInput, + selectedParentName, + selectParentFromBrowser, + onSelectParent, + handleSearch, + clearSelectedParent, + setIsFocusedOnInput, + } = useParentSelector({ + entityType: EntityType.GlossaryNode, + entityData, + selectedParentUrn, + setSelectedParentUrn, + }); - function onSelectParentNode(parentNodeUrn: string) { - const selectedNode = nodeSearchResults.find((result) => result.entity.urn === parentNodeUrn); - if (selectedNode) { - setSelectedParentUrn(parentNodeUrn); - const displayName = entityRegistry.getDisplayName(selectedNode.entity.type, selectedNode.entity); - setSelectedParentName(displayName); - } - } - - function clearSelectedParent() { - setSelectedParentUrn(''); - setSelectedParentName(''); - setSearchQuery(''); - } - - function selectNodeFromBrowser(urn: string, displayName: string) { - setIsFocusedOnInput(false); - setSelectedParentUrn(urn); - setSelectedParentName(displayName); + let nodeSearchResults: SearchResult[] = []; + if (isMoving) { + nodeSearchResults = searchResults.filter((r) => filterResultsForMove(r.entity as GlossaryNode, entityDataUrn)); } const isShowingGlossaryBrowser = !searchQuery && isFocusedOnInput; @@ -91,7 +60,7 @@ function NodeParentSelect(props: Props) { allowClear filterOption={false} value={selectedParentName} - onSelect={onSelectParentNode} + onSelect={onSelectParent} onSearch={handleSearch} onClear={clearSelectedParent} onFocus={() => setIsFocusedOnInput(true)} @@ -107,7 +76,7 @@ function NodeParentSelect(props: Props) { diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/useDeleteEntity.tsx b/datahub-web-react/src/app/entity/shared/EntityDropdown/useDeleteEntity.tsx index c4647b995337bd..1e4737135ed748 100644 --- a/datahub-web-react/src/app/entity/shared/EntityDropdown/useDeleteEntity.tsx +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/useDeleteEntity.tsx @@ -6,6 +6,7 @@ import { getDeleteEntityMutation } from '../../../shared/deleteUtils'; import analytics, { EventType } from '../../../analytics'; import { useGlossaryEntityData } from '../GlossaryEntityContext'; import { getParentNodeToUpdate, updateGlossarySidebar } from '../../../glossary/utils'; +import { useHandleDeleteDomain } from './useHandleDeleteDomain'; /** * Performs the flow for deleting an entity of a given type. @@ -25,6 +26,7 @@ function useDeleteEntity( const [hasBeenDeleted, setHasBeenDeleted] = useState(false); const entityRegistry = useEntityRegistry(); const { isInGlossaryContext, urnsToUpdate, setUrnsToUpdate } = useGlossaryEntityData(); + const { handleDeleteDomain } = useHandleDeleteDomain({ entityData, urn }); const maybeDeleteEntity = getDeleteEntityMutation(type)(); const deleteEntity = (maybeDeleteEntity && maybeDeleteEntity[0]) || undefined; @@ -47,6 +49,11 @@ function useDeleteEntity( duration: 2, }); } + + if (entityData.type === EntityType.Domain) { + handleDeleteDomain(); + } + setTimeout( () => { setHasBeenDeleted(true); diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/useHandleDeleteDomain.ts b/datahub-web-react/src/app/entity/shared/EntityDropdown/useHandleDeleteDomain.ts new file mode 100644 index 00000000000000..ebbb8f9968a6ae --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/useHandleDeleteDomain.ts @@ -0,0 +1,27 @@ +import { useApolloClient } from '@apollo/client'; +import { GenericEntityProperties } from '../types'; +import { removeFromListDomainsCache } from '../../../domain/utils'; +import { useDomainsContext } from '../../../domain/DomainsContext'; + +interface DeleteDomainProps { + entityData: GenericEntityProperties; + urn: string; +} + +export function useHandleDeleteDomain({ entityData, urn }: DeleteDomainProps) { + const client = useApolloClient(); + const { parentDomainsToUpdate, setParentDomainsToUpdate } = useDomainsContext(); + + const handleDeleteDomain = () => { + if (entityData.parentDomains && entityData.parentDomains.domains.length > 0) { + const parentDomainUrn = entityData.parentDomains.domains[0].urn; + + removeFromListDomainsCache(client, urn, 1, 1000, parentDomainUrn); + setParentDomainsToUpdate([...parentDomainsToUpdate, parentDomainUrn]); + } else { + removeFromListDomainsCache(client, urn, 1, 1000); + } + }; + + return { handleDeleteDomain }; +} diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/useHandleMoveDomainComplete.ts b/datahub-web-react/src/app/entity/shared/EntityDropdown/useHandleMoveDomainComplete.ts new file mode 100644 index 00000000000000..81f19331e18b77 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/useHandleMoveDomainComplete.ts @@ -0,0 +1,40 @@ +import { useApolloClient } from '@apollo/client'; +import { removeFromListDomainsCache, updateListDomainsCache } from '../../../domain/utils'; +import { useDomainsContext } from '../../../domain/DomainsContext'; +import { Domain } from '../../../../types.generated'; +import analytics from '../../../analytics/analytics'; +import { EventType } from '../../../analytics'; + +export function useHandleMoveDomainComplete() { + const client = useApolloClient(); + const { entityData, parentDomainsToUpdate, setParentDomainsToUpdate } = useDomainsContext(); + + const handleMoveDomainComplete = (urn: string, newParentUrn?: string) => { + if (!entityData) return; + + const domain = entityData as Domain; + const oldParentUrn = domain.parentDomains?.domains.length ? domain.parentDomains.domains[0].urn : undefined; + + analytics.event({ + type: EventType.MoveDomainEvent, + oldParentDomainUrn: oldParentUrn, + parentDomainUrn: newParentUrn, + }); + + removeFromListDomainsCache(client, urn, 1, 1000, oldParentUrn); + updateListDomainsCache( + client, + domain.urn, + undefined, + domain.properties?.name ?? '', + domain.properties?.description ?? '', + newParentUrn, + ); + const newParentDomainsToUpdate = [...parentDomainsToUpdate]; + if (oldParentUrn) newParentDomainsToUpdate.push(oldParentUrn); + if (newParentUrn) newParentDomainsToUpdate.push(newParentUrn); + setParentDomainsToUpdate(newParentDomainsToUpdate); + }; + + return { handleMoveDomainComplete }; +} diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/useParentSelector.ts b/datahub-web-react/src/app/entity/shared/EntityDropdown/useParentSelector.ts new file mode 100644 index 00000000000000..32b5d8ca790cc7 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/useParentSelector.ts @@ -0,0 +1,76 @@ +import { useEffect, useState } from 'react'; +import { useGetSearchResultsLazyQuery } from '../../../../graphql/search.generated'; +import { EntityType } from '../../../../types.generated'; +import { useEntityRegistry } from '../../../useEntityRegistry'; +import { GenericEntityProperties } from '../types'; + +interface Props { + entityType: EntityType; + entityData: GenericEntityProperties | null; + selectedParentUrn: string; + setSelectedParentUrn: (parent: string) => void; +} + +export default function useParentSelector({ entityType, entityData, selectedParentUrn, setSelectedParentUrn }: Props) { + const [selectedParentName, setSelectedParentName] = useState(); + const [isFocusedOnInput, setIsFocusedOnInput] = useState(false); + const [searchQuery, setSearchQuery] = useState(''); + const entityRegistry = useEntityRegistry(); + + const [search, { data }] = useGetSearchResultsLazyQuery(); + const searchResults = data?.search?.searchResults || []; + + useEffect(() => { + if (entityData && selectedParentUrn === entityData.urn) { + const displayName = entityRegistry.getDisplayName(entityType, entityData); + setSelectedParentName(displayName); + } + }, [entityData, entityRegistry, selectedParentUrn, entityData?.urn, entityType]); + + function handleSearch(text: string) { + setSearchQuery(text); + search({ + variables: { + input: { + type: entityType, + query: text, + start: 0, + count: 5, + }, + }, + }); + } + + function onSelectParent(parentUrn: string) { + const selectedParent = searchResults.find((result) => result.entity.urn === parentUrn); + if (selectedParent) { + setSelectedParentUrn(parentUrn); + const displayName = entityRegistry.getDisplayName(selectedParent.entity.type, selectedParent.entity); + setSelectedParentName(displayName); + } + } + + function clearSelectedParent() { + setSelectedParentUrn(''); + setSelectedParentName(undefined); + setSearchQuery(''); + } + + function selectParentFromBrowser(urn: string, displayName: string) { + setIsFocusedOnInput(false); + setSelectedParentUrn(urn); + setSelectedParentName(displayName); + } + + return { + searchQuery, + searchResults, + isFocusedOnInput, + selectedParentName, + onSelectParent, + handleSearch, + setIsFocusedOnInput, + selectParentFromBrowser, + clearSelectedParent, + }; +} diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/utils.ts b/datahub-web-react/src/app/entity/shared/EntityDropdown/utils.ts index 9e3d14cfd32e14..0a4c2c34441a44 100644 --- a/datahub-web-react/src/app/entity/shared/EntityDropdown/utils.ts +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/utils.ts @@ -1,7 +1,11 @@ -import { EntityType } from '../../../../types.generated'; +import { EntityType, PlatformPrivileges } from '../../../../types.generated'; import { GenericEntityProperties } from '../types'; -export function isDeleteDisabled(entityType: EntityType, entityData: GenericEntityProperties | null) { +export function isDeleteDisabled( + entityType: EntityType, + entityData: GenericEntityProperties | null, + platformPrivileges: PlatformPrivileges | null | undefined, +) { if (entityType === EntityType.GlossaryTerm || entityType === EntityType.GlossaryNode) { const entityHasChildren = !!entityData?.children?.total; const canManageGlossaryEntity = !!entityData?.privileges?.canManageEntity; @@ -11,5 +15,47 @@ export function isDeleteDisabled(entityType: EntityType, entityData: GenericEnti if (entityType === EntityType.DataProduct) { return false; // TODO: update with permissions } + if (entityType === EntityType.Domain) { + const entityHasChildren = !!entityData?.children?.total; + const canManageDomains = !!platformPrivileges?.manageDomains; + const canDeleteDomainEntity = !entityHasChildren && canManageDomains; + return !canDeleteDomainEntity; + } + return false; +} + +export function isMoveDisabled( + entityType: EntityType, + entityData: GenericEntityProperties | null, + platformPrivileges: PlatformPrivileges | null | undefined, +) { + if (entityType === EntityType.GlossaryTerm || entityType === EntityType.GlossaryNode) { + const canManageGlossaryEntity = !!entityData?.privileges?.canManageEntity; + return !canManageGlossaryEntity; + } + if (entityType === EntityType.Domain) { + const canManageDomains = !!platformPrivileges?.manageDomains; + return !canManageDomains; + } + return false; +} + +export function shouldDisplayChildDeletionWarning( + entityType: EntityType, + entityData: GenericEntityProperties | null, + platformPrivileges: PlatformPrivileges | null | undefined, +) { + if (entityType === EntityType.GlossaryTerm || entityType === EntityType.GlossaryNode) { + const entityHasChildren = !!entityData?.children?.total; + const canManageGlossaryEntity = !!entityData?.privileges?.canManageEntity; + const hasTooltip = entityHasChildren && canManageGlossaryEntity; + return hasTooltip; + } + if (entityType === EntityType.Domain) { + const entityHasChildren = !!entityData?.children?.total; + const canManageDomains = !!platformPrivileges?.manageDomains; + const hasTooltip = entityHasChildren && canManageDomains; + return hasTooltip; + } return false; } diff --git a/datahub-web-react/src/app/entity/shared/ExternalUrlButton.tsx b/datahub-web-react/src/app/entity/shared/ExternalUrlButton.tsx index 9677af07766042..dce74c02cdb345 100644 --- a/datahub-web-react/src/app/entity/shared/ExternalUrlButton.tsx +++ b/datahub-web-react/src/app/entity/shared/ExternalUrlButton.tsx @@ -1,28 +1,11 @@ -import { ArrowRightOutlined } from '@ant-design/icons'; -import { Button } from 'antd'; import React from 'react'; -import styled from 'styled-components/macro'; import { EntityType } from '../../../types.generated'; import analytics, { EventType, EntityActionType } from '../../analytics'; +import UrlButton from './UrlButton'; const GITHUB_LINK = 'github.com'; const GITHUB = 'GitHub'; -const ExternalUrlWrapper = styled.span` - font-size: 12px; -`; - -const StyledButton = styled(Button)` - > :hover { - text-decoration: underline; - } - &&& { - padding-bottom: 0px; - } - padding-left: 12px; - padding-right: 12px; -`; - interface Props { externalUrl: string; platformName?: string; @@ -46,17 +29,8 @@ export default function ExternalUrlButton({ externalUrl, platformName, entityTyp } return ( - - - {displayedName ? `View in ${displayedName}` : 'View link'}{' '} - - - + + {displayedName ? `View in ${displayedName}` : 'View link'} + ); } diff --git a/datahub-web-react/src/app/entity/shared/UrlButton.tsx b/datahub-web-react/src/app/entity/shared/UrlButton.tsx new file mode 100644 index 00000000000000..a6f6da4a60ad57 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/UrlButton.tsx @@ -0,0 +1,37 @@ +import React, { ReactNode } from 'react'; +import { ArrowRightOutlined } from '@ant-design/icons'; +import { Button } from 'antd'; +import styled from 'styled-components/macro'; + +const UrlButtonContainer = styled.span` + font-size: 12px; +`; + +const StyledButton = styled(Button)` + > :hover { + text-decoration: underline; + } + &&& { + padding-bottom: 0px; + } + padding-left: 12px; + padding-right: 12px; +`; + +interface Props { + href: string; + children: ReactNode; + onClick?: () => void; +} + +const NOOP = () => {}; + +export default function UrlButton({ href, children, onClick = NOOP }: Props) { + return ( + + + {children} + + + ); +} diff --git a/datahub-web-react/src/app/entity/shared/__tests__/utils.test.ts b/datahub-web-react/src/app/entity/shared/__tests__/utils.test.ts deleted file mode 100644 index 86dec46528b494..00000000000000 --- a/datahub-web-react/src/app/entity/shared/__tests__/utils.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { getMatchPrioritizingPrimary } from '../utils'; - -const MOCK_MATCHED_FIELDS = [ - { - name: 'fieldPaths', - value: 'rain', - }, - { - name: 'description', - value: 'rainbow', - }, - { - name: 'fieldPaths', - value: 'rainbow', - }, - { - name: 'fieldPaths', - value: 'rainbows', - }, -]; - -describe('utils', () => { - describe('getMatchPrioritizingPrimary', () => { - it('prioritizes exact match', () => { - global.window.location.search = 'query=rainbow'; - const match = getMatchPrioritizingPrimary(MOCK_MATCHED_FIELDS, 'fieldPaths'); - expect(match?.value).toEqual('rainbow'); - expect(match?.name).toEqual('fieldPaths'); - }); - it('will accept first contains match', () => { - global.window.location.search = 'query=bow'; - const match = getMatchPrioritizingPrimary(MOCK_MATCHED_FIELDS, 'fieldPaths'); - expect(match?.value).toEqual('rainbow'); - expect(match?.name).toEqual('fieldPaths'); - }); - }); -}); diff --git a/datahub-web-react/src/app/entity/shared/components/styled/StripMarkdownText.tsx b/datahub-web-react/src/app/entity/shared/components/styled/StripMarkdownText.tsx index 59293c2b0eee5b..212813ffcb6435 100644 --- a/datahub-web-react/src/app/entity/shared/components/styled/StripMarkdownText.tsx +++ b/datahub-web-react/src/app/entity/shared/components/styled/StripMarkdownText.tsx @@ -17,6 +17,7 @@ export type Props = { suffix?: JSX.Element; limit?: number; shouldWrap?: boolean; + customRender?: (text: string) => JSX.Element; }; export const removeMarkdown = (text: string) => { @@ -29,7 +30,7 @@ export const removeMarkdown = (text: string) => { .replace(/^•/, ''); // remove first • }; -export default function NoMarkdownViewer({ children, readMore, suffix, limit, shouldWrap }: Props) { +export default function NoMarkdownViewer({ children, customRender, readMore, suffix, limit, shouldWrap }: Props) { let plainText = removeMarkdown(children || ''); if (limit) { @@ -44,7 +45,8 @@ export default function NoMarkdownViewer({ children, readMore, suffix, limit, sh return ( - {plainText} {showReadMore && <>{readMore}} {suffix} + {customRender ? customRender(plainText) : plainText} + {showReadMore && <>{readMore}} {suffix} ); } diff --git a/datahub-web-react/src/app/entity/shared/components/styled/StyledTag.tsx b/datahub-web-react/src/app/entity/shared/components/styled/StyledTag.tsx index c1a23811fdd7e0..08087bfd79b8e9 100644 --- a/datahub-web-react/src/app/entity/shared/components/styled/StyledTag.tsx +++ b/datahub-web-react/src/app/entity/shared/components/styled/StyledTag.tsx @@ -6,7 +6,15 @@ export const generateColor = new ColorHash({ saturation: 0.9, }); -export const StyledTag = styled(Tag)<{ $color: any; $colorHash?: string; fontSize?: number }>` +export const StyledTag = styled(Tag)<{ $color: any; $colorHash?: string; fontSize?: number; highlightTag?: boolean }>` + &&& { + ${(props) => + props.highlightTag && + ` + background: ${props.theme.styles['highlight-color']}; + border: 1px solid ${props.theme.styles['highlight-border-color']}; + `} + } ${(props) => props.fontSize && `font-size: ${props.fontSize}px;`} ${(props) => props.$colorHash && diff --git a/datahub-web-react/src/app/entity/shared/constants.ts b/datahub-web-react/src/app/entity/shared/constants.ts index 447780fb0d6410..9df5923d185423 100644 --- a/datahub-web-react/src/app/entity/shared/constants.ts +++ b/datahub-web-react/src/app/entity/shared/constants.ts @@ -21,6 +21,7 @@ export const ANTD_GRAY = { }; export const ANTD_GRAY_V2 = { + 1: '#F8F9Fa', 2: '#F3F5F6', 5: '#DDE0E4', 6: '#B2B8BD', diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/EntityProfile.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/EntityProfile.tsx index 8a559013c892c9..5384eb94429ed4 100644 --- a/datahub-web-react/src/app/entity/shared/containers/profile/EntityProfile.tsx +++ b/datahub-web-react/src/app/entity/shared/containers/profile/EntityProfile.tsx @@ -45,6 +45,7 @@ import { LINEAGE_GRAPH_TIME_FILTER_ID, } from '../../../../onboarding/config/LineageGraphOnboardingConfig'; import { useAppConfig } from '../../../../useAppConfig'; +import { useUpdateDomainEntityDataOnChange } from '../../../../domain/utils'; type Props = { urn: string; @@ -212,6 +213,7 @@ export const EntityProfile = ({ useGetDataForProfile({ urn, entityType, useEntityQuery, getOverrideProperties }); useUpdateGlossaryEntityDataOnChange(entityData, entityType); + useUpdateDomainEntityDataOnChange(entityData, entityType); const maybeUpdateEntity = useUpdateQuery?.({ onCompleted: () => refetch(), diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealth.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealth.tsx index baef67a3d1c88e..30713afa888b84 100644 --- a/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealth.tsx +++ b/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealth.tsx @@ -2,7 +2,7 @@ import React from 'react'; import styled from 'styled-components'; import { Link } from 'react-router-dom'; import { Health } from '../../../../../../types.generated'; -import { getHealthSummaryIcon, isUnhealthy } from '../../../../../shared/health/healthUtils'; +import { getHealthSummaryIcon, HealthSummaryIconType, isUnhealthy } from '../../../../../shared/health/healthUtils'; import { EntityHealthPopover } from './EntityHealthPopover'; const Container = styled.div` @@ -14,17 +14,19 @@ const Container = styled.div` type Props = { health: Health[]; baseUrl: string; + fontSize?: number; + tooltipPlacement?: any; }; -export const EntityHealth = ({ health, baseUrl }: Props) => { +export const EntityHealth = ({ health, baseUrl, fontSize, tooltipPlacement }: Props) => { const unhealthy = isUnhealthy(health); - const icon = getHealthSummaryIcon(health); + const icon = getHealthSummaryIcon(health, HealthSummaryIconType.FILLED, fontSize); return ( <> {(unhealthy && ( - + {icon} diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealthPopover.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealthPopover.tsx index 0d327a54a62d11..4dde3ffcbb6a41 100644 --- a/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealthPopover.tsx +++ b/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityHealthPopover.tsx @@ -50,10 +50,12 @@ type Props = { health: Health[]; baseUrl: string; children: React.ReactNode; + fontSize?: number; + placement?: any; }; -export const EntityHealthPopover = ({ health, baseUrl, children }: Props) => { - const icon = getHealthSummaryIcon(health, HealthSummaryIconType.OUTLINED); +export const EntityHealthPopover = ({ health, baseUrl, children, fontSize, placement = 'right' }: Props) => { + const icon = getHealthSummaryIcon(health, HealthSummaryIconType.OUTLINED, fontSize); const message = getHealthSummaryMessage(health); return ( { } color="#262626" - placement="right" + placement={placement} zIndex={10000000} > {children} diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityName.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityName.tsx index d6df1cf8818df1..762bd5f9111a0e 100644 --- a/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityName.tsx +++ b/datahub-web-react/src/app/entity/shared/containers/profile/header/EntityName.tsx @@ -33,17 +33,27 @@ function EntityName(props: Props) { const { urn, entityType, entityData } = useEntityData(); const entityName = entityData ? entityRegistry.getDisplayName(entityType, entityData) : ''; const [updatedName, setUpdatedName] = useState(entityName); + const [isEditing, setIsEditing] = useState(false); useEffect(() => { setUpdatedName(entityName); }, [entityName]); - const [updateName] = useUpdateNameMutation(); + const [updateName, { loading: isMutatingName }] = useUpdateNameMutation(); - const handleSaveName = (name: string) => { + const handleStartEditing = () => { + setIsEditing(true); + }; + + const handleChangeName = (name: string) => { + if (name === entityName) { + setIsEditing(false); + return; + } setUpdatedName(name); updateName({ variables: { input: { name, urn } } }) .then(() => { + setIsEditing(false); message.success({ content: 'Name Updated', duration: 2 }); refetch(); if (isInGlossaryContext) { @@ -62,13 +72,19 @@ function EntityName(props: Props) { return ( <> {isNameEditable ? ( - + {updatedName} ) : ( - - {entityData && entityRegistry.getDisplayName(entityType, entityData)} - + {entityName} )} ); diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentContainer.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentContainer.tsx index 5e87f093c37787..0eb223c04d4399 100644 --- a/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentContainer.tsx +++ b/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentContainer.tsx @@ -50,6 +50,7 @@ function PlatformContentContainer() { parentContainers={entityData?.parentContainers?.containers} parentContainersRef={contentRef} areContainersTruncated={isContentTruncated} + parentEntities={entityData?.parentDomains?.domains} /> ); } diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentView.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentView.tsx index 5605bacc1d4e43..1090dac501d0b2 100644 --- a/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentView.tsx +++ b/datahub-web-react/src/app/entity/shared/containers/profile/header/PlatformContent/PlatformContentView.tsx @@ -2,18 +2,20 @@ import React from 'react'; import styled from 'styled-components'; import { Typography, Image } from 'antd'; import { Maybe } from 'graphql/jsutils/Maybe'; -import { Container, GlossaryNode } from '../../../../../../../types.generated'; +import { Container, Entity } from '../../../../../../../types.generated'; import { ANTD_GRAY } from '../../../../constants'; import ContainerLink from './ContainerLink'; -import ParentNodesView, { +import { StyledRightOutlined, ParentNodesWrapper as ParentContainersWrapper, Ellipsis, StyledTooltip, } from './ParentNodesView'; +import ParentEntities from '../../../../../../search/filters/ParentEntities'; const LogoIcon = styled.span` display: flex; + gap: 4px; margin-right: 8px; `; @@ -74,14 +76,14 @@ interface Props { typeIcon?: JSX.Element; entityType?: string; parentContainers?: Maybe[] | null; - parentNodes?: GlossaryNode[] | null; + parentEntities?: Entity[] | null; parentContainersRef: React.RefObject; areContainersTruncated: boolean; } function PlatformContentView(props: Props) { const { - parentNodes, + parentEntities, platformName, platformLogoUrl, platformNames, @@ -102,7 +104,7 @@ function PlatformContentView(props: Props) { {typeIcon && {typeIcon}} {entityType} - {(!!platformName || !!instanceId || !!parentContainers?.length || !!parentNodes?.length) && ( + {(!!platformName || !!instanceId || !!parentContainers?.length || !!parentEntities?.length) && ( )} {platformName && ( @@ -145,7 +147,7 @@ function PlatformContentView(props: Props) { {directParentContainer && } - + ); } diff --git a/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx b/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx index fe49409b006538..405442e8d7f506 100644 --- a/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx +++ b/datahub-web-react/src/app/entity/shared/containers/profile/sidebar/Domain/SetDomainModal.tsx @@ -2,14 +2,16 @@ import React, { useRef, useState } from 'react'; import { Button, Form, message, Modal, Select } from 'antd'; import { useGetSearchResultsLazyQuery } from '../../../../../../../graphql/search.generated'; -import { Entity, EntityType } from '../../../../../../../types.generated'; +import { Domain, Entity, EntityType } from '../../../../../../../types.generated'; import { useBatchSetDomainMutation } from '../../../../../../../graphql/mutations.generated'; import { useEntityRegistry } from '../../../../../../useEntityRegistry'; import { useEnterKeyListener } from '../../../../../../shared/useEnterKeyListener'; -import { useGetRecommendations } from '../../../../../../shared/recommendation'; import { DomainLabel } from '../../../../../../shared/DomainLabel'; import { handleBatchError } from '../../../../utils'; import { tagRender } from '../tagRenderer'; +import { BrowserWrapper } from '../../../../../../shared/tags/AddTagsTermsModal'; +import DomainNavigator from '../../../../../../domain/nestedDomains/domainNavigator/DomainNavigator'; +import ClickOutside from '../../../../../../shared/ClickOutside'; type Props = { urns: string[]; @@ -28,6 +30,7 @@ type SelectedDomain = { export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOkOverride, titleOverride }: Props) => { const entityRegistry = useEntityRegistry(); + const [isFocusedOnInput, setIsFocusedOnInput] = useState(false); const [inputValue, setInputValue] = useState(''); const [selectedDomain, setSelectedDomain] = useState( defaultValue @@ -42,8 +45,8 @@ export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOk const domainSearchResults = domainSearchData?.search?.searchResults?.map((searchResult) => searchResult.entity) || []; const [batchSetDomainMutation] = useBatchSetDomainMutation(); - const [recommendedData] = useGetRecommendations([EntityType.Domain]); const inputEl = useRef(null); + const isShowingDomainNavigator = !inputValue && isFocusedOnInput; const onModalClose = () => { setInputValue(''); @@ -74,7 +77,7 @@ export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOk ); }; - const domainResult = !inputValue || inputValue.length === 0 ? recommendedData : domainSearchResults; + const domainResult = !inputValue || inputValue.length === 0 ? [] : domainSearchResults; const domainSearchOptions = domainResult?.map((result) => { return renderSearchResult(result); @@ -95,6 +98,15 @@ export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOk } }; + function selectDomainFromBrowser(domain: Domain) { + setIsFocusedOnInput(false); + setSelectedDomain({ + displayName: entityRegistry.getDisplayName(EntityType.Domain, domain), + type: EntityType.Domain, + urn: domain.urn, + }); + } + const onDeselectDomain = () => { setInputValue(''); setSelectedDomain(undefined); @@ -148,6 +160,11 @@ export const SetDomainModal = ({ urns, onCloseModal, refetch, defaultValue, onOk setInputValue(''); } + function handleCLickOutside() { + // delay closing the domain navigator so we don't get a UI "flash" between showing search results and navigator + setTimeout(() => setIsFocusedOnInput(false), 0); + } + return (
- + + + + + +
diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/AccessManagement.tsx b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/AccessManagement.tsx new file mode 100644 index 00000000000000..c8125693674190 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/AccessManagement.tsx @@ -0,0 +1,115 @@ +import React from 'react'; +import styled from 'styled-components'; +import { Button, Table } from 'antd'; +import { useBaseEntity } from '../../../EntityContext'; +import { GetDatasetQuery, useGetExternalRolesQuery } from '../../../../../../graphql/dataset.generated'; +import { useGetMeQuery } from '../../../../../../graphql/me.generated'; +import { handleAccessRoles } from './utils'; +import AccessManagerDescription from './AccessManagerDescription'; + +const StyledTable = styled(Table)` + overflow: inherit; + height: inherit; + + &&& .ant-table-cell { + background-color: #fff; + } + &&& .ant-table-thead .ant-table-cell { + font-weight: 600; + font-size: 12px; + color: '#898989'; + } + && + .ant-table-thead + > tr + > th:not(:last-child):not(.ant-table-selection-column):not(.ant-table-row-expand-icon-cell):not([colspan])::before { + border: 1px solid #f0f0f0; + } +` as typeof Table; + +const StyledSection = styled.section` + background-color: #fff; + color: black; + width: 83px; + text-align: center; + border-radius: 3px; + border: none; + font-weight: bold; +`; + +const AccessButton = styled(Button)` + background-color: #1890ff; + color: white; + width: 80px; + height: 30px; + border-radius: 3.5px; + border: none; + font-weight: bold; + &:hover { + background-color: #18baff; + color: white; + width: 80px; + height: 30px; + border-radius: 3.5px; + border: none; + font-weight: bold; + } +`; + +export default function AccessManagement() { + const { data: loggedInUser } = useGetMeQuery({ fetchPolicy: 'cache-first' }); + const baseEntity = useBaseEntity(); + const { data: externalRoles } = useGetExternalRolesQuery({ + variables: { urn: baseEntity?.dataset?.urn as string }, + skip: !baseEntity?.dataset?.urn, + }); + + const columns = [ + { + title: 'Role Name', + dataIndex: 'name', + key: 'name', + }, + { + title: 'Description', + dataIndex: 'description', + key: 'description', + render: (roleDescription) => { + return ; + }, + }, + { + title: 'Access Type', + dataIndex: 'accessType', + key: 'accessType', + }, + { + title: 'Access', + dataIndex: 'hasAccess', + key: 'hasAccess', + render: (hasAccess, record) => { + if (hasAccess) { + return Provisioned; + } + if (record?.url) { + return ( + { + e.preventDefault(); + window.open(record.url); + }} + > + Request + + ); + } + return ; + }, + hidden: true, + }, + ]; + + return ( + + ); +} diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/AccessManagerDescription.tsx b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/AccessManagerDescription.tsx new file mode 100644 index 00000000000000..c87a499e34ac0f --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/AccessManagerDescription.tsx @@ -0,0 +1,38 @@ +import React, { useState } from 'react'; +import styled from 'styled-components'; +import { Typography } from 'antd'; + +export type Props = { + description: any; +}; + +const DescriptionContainer = styled.div` + position: relative; + display: flex; + flex-direction: column; + width: 500px; + height: 100%; + min-height: 22px; +`; + +export default function AccessManagerDescription({ description }: Props) { + const shouldTruncateDescription = description.length > 150; + const [expanded, setIsExpanded] = useState(!shouldTruncateDescription); + const finalDescription = expanded ? description : description.slice(0, 150); + const toggleExpanded = () => { + setIsExpanded(!expanded); + }; + + return ( + + {finalDescription} + { + toggleExpanded(); + }} + > + {(shouldTruncateDescription && (expanded ? ' Read Less' : '...Read More')) || undefined} + + + ); +} diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/__tests__/AccessManagement.test.ts b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/__tests__/AccessManagement.test.ts new file mode 100644 index 00000000000000..53c7b483d94280 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/__tests__/AccessManagement.test.ts @@ -0,0 +1,267 @@ +import { handleAccessRoles } from '../utils'; +import { GetExternalRolesQuery } from '../../../../../../../graphql/dataset.generated'; +import { GetMeQuery } from '../../../../../../../graphql/me.generated'; + +describe('handleAccessRoles', () => { + it('should properly map the externalroles and loggedin user', () => { + const externalRolesQuery: GetExternalRolesQuery = { + dataset: { + access: { + roles: [ + { + role: { + id: 'accessRole', + properties: { + name: 'accessRole', + description: + 'This role access is required by the developers to test and deploy the code also adding few more details to check the description length for the given data and hence check the condition of read more and read less ', + type: 'READ', + requestUrl: 'https://www.google.com/', + }, + urn: 'urn:li:role:accessRole', + actors: { + users: null, + }, + }, + }, + ], + }, + __typename: 'Dataset', + }, + }; + + const GetMeQueryUser: GetMeQuery = { + me: { + corpUser: { + urn: 'urn:li:corpuser:datahub', + username: 'datahub', + info: { + active: true, + displayName: 'DataHub', + title: 'DataHub Root User', + firstName: null, + lastName: null, + fullName: null, + email: null, + __typename: 'CorpUserInfo', + }, + editableProperties: { + displayName: null, + title: null, + pictureLink: + 'https://raw.githubusercontent.com/datahub-project/datahub/master/datahub-web-react/src/images/default_avatar.png', + teams: [], + skills: [], + __typename: 'CorpUserEditableProperties', + }, + settings: { + appearance: { + showSimplifiedHomepage: false, + __typename: 'CorpUserAppearanceSettings', + }, + views: null, + __typename: 'CorpUserSettings', + }, + __typename: 'CorpUser', + }, + platformPrivileges: { + viewAnalytics: true, + managePolicies: true, + manageIdentities: true, + generatePersonalAccessTokens: true, + manageIngestion: true, + manageSecrets: true, + manageDomains: true, + manageTests: true, + manageGlossaries: true, + manageUserCredentials: true, + manageTags: true, + createDomains: true, + createTags: true, + manageGlobalViews: true, + manageOwnershipTypes: true, + __typename: 'PlatformPrivileges', + }, + __typename: 'AuthenticatedUser', + }, + }; + const externalRole = handleAccessRoles(externalRolesQuery, GetMeQueryUser); + expect(externalRole).toMatchObject([ + { + name: 'accessRole', + description: + 'This role access is required by the developers to test and deploy the code also adding few more details to check the description length for the given data and hence check the condition of read more and read less ', + accessType: 'READ', + hasAccess: false, + url: 'https://www.google.com/', + }, + ]); + }); + it('should return empty array', () => { + const externalRolesQuery: GetExternalRolesQuery = { + dataset: { + access: null, + __typename: 'Dataset', + }, + }; + + const GetMeQueryUser: GetMeQuery = { + me: { + corpUser: { + urn: 'urn:li:corpuser:datahub', + username: 'datahub', + info: { + active: true, + displayName: 'DataHub', + title: 'DataHub Root User', + firstName: null, + lastName: null, + fullName: null, + email: null, + __typename: 'CorpUserInfo', + }, + editableProperties: { + displayName: null, + title: null, + pictureLink: + 'https://raw.githubusercontent.com/datahub-project/datahub/master/datahub-web-react/src/images/default_avatar.png', + teams: [], + skills: [], + __typename: 'CorpUserEditableProperties', + }, + settings: { + appearance: { + showSimplifiedHomepage: false, + __typename: 'CorpUserAppearanceSettings', + }, + views: null, + __typename: 'CorpUserSettings', + }, + __typename: 'CorpUser', + }, + platformPrivileges: { + viewAnalytics: true, + managePolicies: true, + manageIdentities: true, + generatePersonalAccessTokens: true, + manageIngestion: true, + manageSecrets: true, + manageDomains: true, + manageTests: true, + manageGlossaries: true, + manageUserCredentials: true, + manageTags: true, + createDomains: true, + createTags: true, + manageGlobalViews: true, + manageOwnershipTypes: true, + __typename: 'PlatformPrivileges', + }, + __typename: 'AuthenticatedUser', + }, + }; + const externalRole = handleAccessRoles(externalRolesQuery, GetMeQueryUser); + expect(externalRole).toMatchObject([]); + }); + it('should properly map the externalroles and loggedin user and access true', () => { + const externalRolesQuery: GetExternalRolesQuery = { + dataset: { + access: { + roles: [ + { + role: { + id: 'accessRole', + properties: { + name: 'accessRole', + description: + 'This role access is required by the developers to test and deploy the code also adding few more details to check the description length for the given data and hence check the condition of read more and read less ', + type: 'READ', + requestUrl: 'https://www.google.com/', + }, + urn: 'urn:li:role:accessRole', + actors: { + users: [ + { + user: { + urn: 'urn:li:corpuser:datahub', + }, + }, + ], + }, + }, + }, + ], + }, + __typename: 'Dataset', + }, + }; + + const GetMeQueryUser: GetMeQuery = { + me: { + corpUser: { + urn: 'urn:li:corpuser:datahub', + username: 'datahub', + info: { + active: true, + displayName: 'DataHub', + title: 'DataHub Root User', + firstName: null, + lastName: null, + fullName: null, + email: null, + __typename: 'CorpUserInfo', + }, + editableProperties: { + displayName: null, + title: null, + pictureLink: + 'https://raw.githubusercontent.com/datahub-project/datahub/master/datahub-web-react/src/images/default_avatar.png', + teams: [], + skills: [], + __typename: 'CorpUserEditableProperties', + }, + settings: { + appearance: { + showSimplifiedHomepage: false, + __typename: 'CorpUserAppearanceSettings', + }, + views: null, + __typename: 'CorpUserSettings', + }, + __typename: 'CorpUser', + }, + platformPrivileges: { + viewAnalytics: true, + managePolicies: true, + manageIdentities: true, + generatePersonalAccessTokens: true, + manageIngestion: true, + manageSecrets: true, + manageDomains: true, + manageTests: true, + manageGlossaries: true, + manageUserCredentials: true, + manageTags: true, + createDomains: true, + createTags: true, + manageGlobalViews: true, + manageOwnershipTypes: true, + __typename: 'PlatformPrivileges', + }, + __typename: 'AuthenticatedUser', + }, + }; + const externalRole = handleAccessRoles(externalRolesQuery, GetMeQueryUser); + + expect(externalRole).toMatchObject([ + { + name: 'accessRole', + description: + 'This role access is required by the developers to test and deploy the code also adding few more details to check the description length for the given data and hence check the condition of read more and read less ', + accessType: 'READ', + hasAccess: true, + url: 'https://www.google.com/', + }, + ]); + }); +}); diff --git a/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/utils.tsx b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/utils.tsx new file mode 100644 index 00000000000000..71e81e8d7de935 --- /dev/null +++ b/datahub-web-react/src/app/entity/shared/tabs/Dataset/AccessManagement/utils.tsx @@ -0,0 +1,27 @@ +export function handleAccessRoles(externalRoles, loggedInUser) { + const accessRoles = new Array(); + if ( + externalRoles?.dataset?.access && + externalRoles?.dataset?.access.roles && + externalRoles?.dataset?.access.roles.length > 0 + ) { + externalRoles?.dataset?.access?.roles?.forEach((userRoles) => { + const role = { + name: userRoles?.role?.properties?.name || ' ', + description: userRoles?.role?.properties?.description || ' ', + accessType: userRoles?.role?.properties?.type || ' ', + hasAccess: + (userRoles?.role?.actors?.users && + userRoles?.role?.actors?.users.length > 0 && + userRoles?.role?.actors?.users?.some( + (user) => user.user.urn === loggedInUser?.me?.corpUser.urn, + )) || + false, + url: userRoles?.role?.properties?.requestUrl || undefined, + }; + accessRoles.push(role); + }); + } + + return accessRoles; +} diff --git a/datahub-web-react/src/app/entity/shared/tabs/Documentation/components/LinkList.tsx b/datahub-web-react/src/app/entity/shared/tabs/Documentation/components/LinkList.tsx index 1aef497ced57bf..bcce994c3f0f80 100644 --- a/datahub-web-react/src/app/entity/shared/tabs/Documentation/components/LinkList.tsx +++ b/datahub-web-react/src/app/entity/shared/tabs/Documentation/components/LinkList.tsx @@ -33,7 +33,7 @@ type LinkListProps = { }; export const LinkList = ({ refetch }: LinkListProps) => { - const { entityData } = useEntityData(); + const { urn: entityUrn, entityData } = useEntityData(); const entityRegistry = useEntityRegistry(); const [removeLinkMutation] = useRemoveLinkMutation(); const links = entityData?.institutionalMemory?.elements || []; @@ -41,7 +41,7 @@ export const LinkList = ({ refetch }: LinkListProps) => { const handleDeleteLink = async (metadata: InstitutionalMemoryMetadata) => { try { await removeLinkMutation({ - variables: { input: { linkUrl: metadata.url, resourceUrn: metadata.associatedUrn } }, + variables: { input: { linkUrl: metadata.url, resourceUrn: metadata.associatedUrn || entityUrn } }, }); message.success({ content: 'Link Removed', duration: 2 }); } catch (e: unknown) { diff --git a/datahub-web-react/src/app/entity/shared/types.ts b/datahub-web-react/src/app/entity/shared/types.ts index e36f5050a24b76..6596711d4e82a6 100644 --- a/datahub-web-react/src/app/entity/shared/types.ts +++ b/datahub-web-react/src/app/entity/shared/types.ts @@ -37,6 +37,7 @@ import { FabricType, BrowsePathV2, DataJobInputOutput, + ParentDomainsResult, } from '../../../types.generated'; import { FetchedEntity } from '../../lineage/types'; @@ -65,6 +66,7 @@ export type EntitySubHeaderSection = { export type GenericEntityProperties = { urn?: string; + type?: EntityType; name?: Maybe; properties?: Maybe<{ description?: Maybe; @@ -98,6 +100,7 @@ export type GenericEntityProperties = { status?: Maybe; deprecation?: Maybe; parentContainers?: Maybe; + parentDomains?: Maybe; children?: Maybe; parentNodes?: Maybe; isAChildren?: Maybe; diff --git a/datahub-web-react/src/app/entity/shared/utils.ts b/datahub-web-react/src/app/entity/shared/utils.ts index 7ec604785d1ffe..a158cc9b7c119b 100644 --- a/datahub-web-react/src/app/entity/shared/utils.ts +++ b/datahub-web-react/src/app/entity/shared/utils.ts @@ -1,9 +1,7 @@ -import * as QueryString from 'query-string'; import { Maybe } from 'graphql/jsutils/Maybe'; -import { Entity, EntityType, MatchedField, EntityRelationshipsResult, DataProduct } from '../../../types.generated'; +import { Entity, EntityType, EntityRelationshipsResult, DataProduct } from '../../../types.generated'; import { capitalizeFirstLetterOnly } from '../../shared/textUtil'; -import { FIELDS_TO_HIGHLIGHT } from '../dataset/search/highlights'; import { GenericEntityProperties } from './types'; export function dictToQueryStringParams(params: Record) { @@ -87,46 +85,6 @@ export const isListSubset = (l1, l2): boolean => { return l1.every((result) => l2.indexOf(result) >= 0); }; -function normalize(value: string) { - return value.trim().toLowerCase(); -} - -function fromQueryGetBestMatch(selectedMatchedFields: MatchedField[], rawQuery: string) { - const query = normalize(rawQuery); - // first lets see if there's an exact match between a field value and the query - const exactMatch = selectedMatchedFields.find((field) => normalize(field.value) === query); - if (exactMatch) { - return exactMatch; - } - - // if no exact match exists, we'll see if the entire query is contained in any of the values - const containedMatch = selectedMatchedFields.find((field) => normalize(field.value).includes(query)); - if (containedMatch) { - return containedMatch; - } - - // otherwise, just return whichever is first - return selectedMatchedFields[0]; -} - -export const getMatchPrioritizingPrimary = ( - matchedFields: MatchedField[], - primaryField: string, -): MatchedField | undefined => { - const { location } = window; - const params = QueryString.parse(location.search, { arrayFormat: 'comma' }); - const query: string = decodeURIComponent(params.query ? (params.query as string) : ''); - - const primaryMatches = matchedFields.filter((field) => field.name === primaryField); - if (primaryMatches.length > 0) { - return fromQueryGetBestMatch(primaryMatches, query); - } - - const matchesThatShouldBeShownOnFE = matchedFields.filter((field) => FIELDS_TO_HIGHLIGHT.has(field.name)); - - return fromQueryGetBestMatch(matchesThatShouldBeShownOnFE, query); -}; - function getGraphqlErrorCode(e) { if (e.graphQLErrors && e.graphQLErrors.length) { const firstError = e.graphQLErrors[0]; diff --git a/datahub-web-react/src/app/entity/user/preview/Preview.tsx b/datahub-web-react/src/app/entity/user/preview/Preview.tsx index 01f68d9065523a..05baefb295b986 100644 --- a/datahub-web-react/src/app/entity/user/preview/Preview.tsx +++ b/datahub-web-react/src/app/entity/user/preview/Preview.tsx @@ -7,6 +7,7 @@ import { useEntityRegistry } from '../../../useEntityRegistry'; import { ANTD_GRAY } from '../../shared/constants'; import { IconStyleType } from '../../Entity'; import { CustomAvatar } from '../../../shared/avatar'; +import SearchTextHighlighter from '../../../search/matches/SearchTextHighlighter'; const PreviewContainer = styled.div` display: flex; @@ -80,11 +81,15 @@ export const Preview = ({ {entityRegistry.getEntityName(EntityType.CorpUser)} - {name || urn} + {name ? : urn} - {title && {title}} + {title && ( + + + + )} diff --git a/datahub-web-react/src/app/glossary/BusinessGlossaryPage.tsx b/datahub-web-react/src/app/glossary/BusinessGlossaryPage.tsx index 2adeb6b1684dcc..11f54cb5078e6e 100644 --- a/datahub-web-react/src/app/glossary/BusinessGlossaryPage.tsx +++ b/datahub-web-react/src/app/glossary/BusinessGlossaryPage.tsx @@ -38,12 +38,6 @@ const MainContentWrapper = styled.div` flex-direction: column; `; -export const BrowserWrapper = styled.div<{ width: number }>` - max-height: 100%; - width: ${(props) => props.width}px; - min-width: ${(props) => props.width}px; -`; - export const MAX_BROWSER_WIDTH = 500; export const MIN_BROWSWER_WIDTH = 200; diff --git a/datahub-web-react/src/app/glossary/GlossarySidebar.tsx b/datahub-web-react/src/app/glossary/GlossarySidebar.tsx index 0bdcbf707ce095..2d620fb06df38c 100644 --- a/datahub-web-react/src/app/glossary/GlossarySidebar.tsx +++ b/datahub-web-react/src/app/glossary/GlossarySidebar.tsx @@ -1,14 +1,8 @@ import React, { useState } from 'react'; -import styled from 'styled-components/macro'; import GlossarySearch from './GlossarySearch'; import GlossaryBrowser from './GlossaryBrowser/GlossaryBrowser'; import { ProfileSidebarResizer } from '../entity/shared/containers/profile/sidebar/ProfileSidebarResizer'; - -const BrowserWrapper = styled.div<{ width: number }>` - max-height: 100%; - width: ${(props) => props.width}px; - min-width: ${(props) => props.width}px; -`; +import { SidebarWrapper } from '../shared/sidebar/components'; export const MAX_BROWSER_WIDTH = 500; export const MIN_BROWSWER_WIDTH = 200; @@ -18,10 +12,10 @@ export default function GlossarySidebar() { return ( <> - + - + setBrowserWith(Math.min(Math.max(width, MIN_BROWSWER_WIDTH), MAX_BROWSER_WIDTH)) diff --git a/datahub-web-react/src/app/ingest/source/builder/constants.ts b/datahub-web-react/src/app/ingest/source/builder/constants.ts index 8d41c3533575a6..61667a941765c3 100644 --- a/datahub-web-react/src/app/ingest/source/builder/constants.ts +++ b/datahub-web-react/src/app/ingest/source/builder/constants.ts @@ -27,6 +27,7 @@ import powerbiLogo from '../../../../images/powerbilogo.png'; import modeLogo from '../../../../images/modelogo.png'; import databricksLogo from '../../../../images/databrickslogo.png'; import verticaLogo from '../../../../images/verticalogo.png'; +import dynamodbLogo from '../../../../images/dynamodblogo.png'; export const ATHENA = 'athena'; export const ATHENA_URN = `urn:li:dataPlatform:${ATHENA}`; @@ -43,6 +44,8 @@ export const DBT = 'dbt'; export const DBT_URN = `urn:li:dataPlatform:${DBT}`; export const DRUID = 'druid'; export const DRUID_URN = `urn:li:dataPlatform:${DRUID}`; +export const DYNAMODB = 'dynamodb'; +export const DYNAMODB_URN = `urn:li:dataPlatform:${DYNAMODB}`; export const ELASTICSEARCH = 'elasticsearch'; export const ELASTICSEARCH_URN = `urn:li:dataPlatform:${ELASTICSEARCH}`; export const FEAST = 'feast'; @@ -107,6 +110,7 @@ export const PLATFORM_URN_TO_LOGO = { [CLICKHOUSE_URN]: clickhouseLogo, [DBT_URN]: dbtLogo, [DRUID_URN]: druidLogo, + [DYNAMODB_URN]: dynamodbLogo, [ELASTICSEARCH_URN]: elasticsearchLogo, [FEAST_URN]: feastLogo, [GLUE_URN]: glueLogo, diff --git a/datahub-web-react/src/app/ingest/source/builder/sources.json b/datahub-web-react/src/app/ingest/source/builder/sources.json index 13643c58f72e1a..b4ea2db018bd84 100644 --- a/datahub-web-react/src/app/ingest/source/builder/sources.json +++ b/datahub-web-react/src/app/ingest/source/builder/sources.json @@ -125,6 +125,13 @@ "docsUrl": "https://datahubproject.io/docs/generated/ingestion/sources/mongodb/", "recipe": "source:\n type: mongodb\n config:\n # Coordinates\n connect_uri: # Your MongoDB connect URI, e.g. \"mongodb://localhost\"\n\n # Credentials\n # Add secret in Secrets Tab with relevant names for each variable\n username: \"${MONGO_USERNAME}\" # Your MongoDB username, e.g. admin\n password: \"${MONGO_PASSWORD}\" # Your MongoDB password, e.g. password_01\n\n # Options (recommended)\n enableSchemaInference: True\n useRandomSampling: True\n maxSchemaSize: 300" }, + { + "urn": "urn:li:dataPlatform:dynamodb", + "name": "dynamodb", + "displayName": "DynamoDB", + "docsUrl": "https://datahubproject.io/docs/metadata-ingestion/", + "recipe": "source:\n type: dynamodb\n config:\n platform_instance: \"AWS_ACCOUNT_ID\"\n aws_access_key_id : '${AWS_ACCESS_KEY_ID}'\n aws_secret_access_key : '${AWS_SECRET_ACCESS_KEY}'\n # User could use the below option to provide a list of primary keys of a table in dynamodb format,\n # those items from given primary keys will be included when we scan the table.\n # For each table we can retrieve up to 16 MB of data, which can contain as many as 100 items.\n # We'll enforce the the primary keys list size not to exceed 100\n # The total items we'll try to retrieve in these two scenarios:\n # 1. If user don't specify include_table_item: we'll retrieve up to 100 items\n # 2. If user specifies include_table_item: we'll retrieve up to 100 items plus user specified items in\n # the table, with a total not more than 200 items\n # include_table_item:\n # table_name:\n # [\n # {\n # 'partition_key_name': { 'attribute_type': 'attribute_value' },\n # 'sort_key_name': { 'attribute_type': 'attribute_value' },\n # },\n # ]" + }, { "urn": "urn:li:dataPlatform:glue", "name": "glue", diff --git a/datahub-web-react/src/app/lineage/LineageEntityNode.tsx b/datahub-web-react/src/app/lineage/LineageEntityNode.tsx index 4526e3a225ce21..f5be1d57db0704 100644 --- a/datahub-web-react/src/app/lineage/LineageEntityNode.tsx +++ b/datahub-web-react/src/app/lineage/LineageEntityNode.tsx @@ -12,11 +12,12 @@ import { getShortenedTitle, nodeHeightFromTitleLength } from './utils/titleUtils import { LineageExplorerContext } from './utils/LineageExplorerContext'; import { useGetEntityLineageLazyQuery } from '../../graphql/lineage.generated'; import { useIsSeparateSiblingsMode } from '../entity/shared/siblingUtils'; -import { centerX, centerY, iconHeight, iconWidth, iconX, iconY, textX, width } from './constants'; +import { centerX, centerY, iconHeight, iconWidth, iconX, iconY, textX, width, healthX, healthY } from './constants'; import LineageEntityColumns from './LineageEntityColumns'; import { convertInputFieldsToSchemaFields } from './utils/columnLineageUtils'; import ManageLineageMenu from './manage/ManageLineageMenu'; import { useGetLineageTimeParams } from './utils/useGetLineageTimeParams'; +import { EntityHealth } from '../entity/shared/containers/profile/header/EntityHealth'; const CLICK_DELAY_THRESHOLD = 1000; const DRAG_DISTANCE_THRESHOLD = 20; @@ -136,6 +137,11 @@ export default function LineageEntityNode({ capitalizeFirstLetterOnly(node.data.subtype) || (node.data.type && entityRegistry.getEntityName(node.data.type)); + // Health + const { health } = node.data; + const baseUrl = node.data.type && node.data.urn && entityRegistry.getEntityUrl(node.data.type, node.data.urn); + const hasHealth = (health && baseUrl) || false; + return ( {unexploredHiddenChildren && (isHovered || isSelected) ? ( @@ -359,6 +365,16 @@ export default function LineageEntityNode({ {getShortenedTitle(node.data.name, width)} )} + + {hasHealth && ( + + )} + {unexploredHiddenChildren && isHovered ? ( ; downstreamRelationships?: Array; + health?: Health[]; }; export type VizNode = { diff --git a/datahub-web-react/src/app/lineage/utils/constructFetchedNode.ts b/datahub-web-react/src/app/lineage/utils/constructFetchedNode.ts index 143b226bda687e..778d0e325f7cb3 100644 --- a/datahub-web-react/src/app/lineage/utils/constructFetchedNode.ts +++ b/datahub-web-react/src/app/lineage/utils/constructFetchedNode.ts @@ -67,6 +67,7 @@ export default function constructFetchedNode( canEditLineage: fetchedNode.canEditLineage, upstreamRelationships: fetchedNode?.upstreamRelationships || [], downstreamRelationships: fetchedNode?.downstreamRelationships || [], + health: fetchedNode?.health, }; // eslint-disable-next-line no-param-reassign diff --git a/datahub-web-react/src/app/lineage/utils/constructTree.ts b/datahub-web-react/src/app/lineage/utils/constructTree.ts index 8374509ad74ebc..7da6fc56b57bd4 100644 --- a/datahub-web-react/src/app/lineage/utils/constructTree.ts +++ b/datahub-web-react/src/app/lineage/utils/constructTree.ts @@ -100,6 +100,7 @@ export default function constructTree( canEditLineage: fetchedEntity?.canEditLineage, upstreamRelationships: fetchedEntity?.upstreamRelationships || [], downstreamRelationships: fetchedEntity?.downstreamRelationships || [], + health: fetchedEntity?.health, }; const lineageConfig = entityRegistry.getLineageVizConfig(entityAndType.type, entityAndType.entity); let updatedLineageConfig = { ...lineageConfig }; diff --git a/datahub-web-react/src/app/permissions/policy/PolicyPrivilegeForm.tsx b/datahub-web-react/src/app/permissions/policy/PolicyPrivilegeForm.tsx index c57273c2ea3d94..1520388a5033a9 100644 --- a/datahub-web-react/src/app/permissions/policy/PolicyPrivilegeForm.tsx +++ b/datahub-web-react/src/app/permissions/policy/PolicyPrivilegeForm.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; import { Form, Select, Tag, Tooltip, Typography } from 'antd'; import styled from 'styled-components/macro'; @@ -9,7 +9,7 @@ import { useGetSearchResultsForMultipleLazyQuery, useGetSearchResultsLazyQuery, } from '../../../graphql/search.generated'; -import { ResourceFilter, PolicyType, EntityType } from '../../../types.generated'; +import { ResourceFilter, PolicyType, EntityType, Domain } from '../../../types.generated'; import { convertLegacyResourceFilter, createCriterionValue, @@ -21,6 +21,9 @@ import { mapResourceTypeToPrivileges, setFieldValues, } from './policyUtils'; +import DomainNavigator from '../../domain/nestedDomains/domainNavigator/DomainNavigator'; +import { BrowserWrapper } from '../../shared/tags/AddTagsTermsModal'; +import ClickOutside from '../../shared/ClickOutside'; type Props = { policyType: PolicyType; @@ -55,6 +58,8 @@ export default function PolicyPrivilegeForm({ setPrivileges, }: Props) { const entityRegistry = useEntityRegistry(); + const [domainInputValue, setDomainInputValue] = useState(''); + const [isFocusedOnInput, setIsFocusedOnInput] = useState(false); // Configuration used for displaying options const { @@ -98,6 +103,7 @@ export default function PolicyPrivilegeForm({ const resourceSelectValue = resourceEntities.map((criterionValue) => criterionValue.value); const domainSelectValue = getFieldValues(resources.filter, 'DOMAIN').map((criterionValue) => criterionValue.value); const privilegesSelectValue = privileges; + const isShowingDomainNavigator = !domainInputValue && isFocusedOnInput; // Construct privilege options for dropdown const platformPrivileges = policiesConfig?.platformPrivileges || []; @@ -193,13 +199,14 @@ export default function PolicyPrivilegeForm({ }; // When a domain is selected, add its urn to the list of domains - const onSelectDomain = (domain) => { + const onSelectDomain = (domainUrn, domainObj?: Domain) => { const filter = resources.filter || { criteria: [], }; + const domainEntity = domainObj || getEntityFromSearchResults(domainSearchResults, domainUrn); const updatedFilter = setFieldValues(filter, 'DOMAIN', [ ...domains, - createCriterionValueWithEntity(domain, getEntityFromSearchResults(domainSearchResults, domain) || null), + createCriterionValueWithEntity(domainUrn, domainEntity || null), ]); setResources({ ...resources, @@ -207,6 +214,11 @@ export default function PolicyPrivilegeForm({ }); }; + function selectDomainFromBrowser(domain: Domain) { + onSelectDomain(domain.urn, domain); + setIsFocusedOnInput(false); + } + // When a domain is deselected, remove its urn from the list of domains const onDeselectDomain = (domain) => { const filter = resources.filter || { @@ -243,6 +255,7 @@ export default function PolicyPrivilegeForm({ // Handle domain search, if the domain type has an associated EntityType mapping. const handleDomainSearch = (text: string) => { const trimmedText: string = text.trim(); + setDomainInputValue(trimmedText); searchDomains({ variables: { input: { @@ -276,6 +289,15 @@ export default function PolicyPrivilegeForm({ : displayStr; }; + function handleCLickOutside() { + // delay closing the domain navigator so we don't get a UI "flash" between showing search results and navigator + setTimeout(() => setIsFocusedOnInput(false), 0); + } + + function handleBlur() { + setDomainInputValue(''); + } + return ( {showResourceFilterInput && ( @@ -342,33 +364,41 @@ export default function PolicyPrivilegeForm({ )} {showResourceFilterInput && ( - Domain}> + Select Domains}> - Search for domains the policy should apply to. If none is selected, policy is applied to{' '} - all resources in all domains. + The policy will apply to any chosen domains and all their nested domains. If none are + selected, the policy is applied to all resources of in all domains. - + + + + + + )} Privileges}> diff --git a/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx b/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx index 36713cfb7ffcfa..36c4c020e71317 100644 --- a/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx +++ b/datahub-web-react/src/app/preview/DefaultPreviewCard.tsx @@ -14,10 +14,10 @@ import { CorpUser, Deprecation, Domain, - ParentNodesResult, EntityPath, DataProduct, Health, + Entity, } from '../../types.generated'; import TagTermGroup from '../shared/tags/TagTermGroup'; import { ANTD_GRAY } from '../entity/shared/constants'; @@ -34,6 +34,7 @@ import ExternalUrlButton from '../entity/shared/ExternalUrlButton'; import EntityPaths from './EntityPaths/EntityPaths'; import { DataProductLink } from '../shared/tags/DataProductLink'; import { EntityHealth } from '../entity/shared/containers/profile/header/EntityHealth'; +import SearchTextHighlighter from '../search/matches/SearchTextHighlighter'; import { getUniqueOwners } from './utils'; const PreviewContainer = styled.div` @@ -173,6 +174,7 @@ interface Props { deprecation?: Deprecation | null; topUsers?: Array | null; externalUrl?: string | null; + entityTitleSuffix?: React.ReactNode; subHeader?: React.ReactNode; snippet?: React.ReactNode; insights?: Array | null; @@ -189,7 +191,7 @@ interface Props { // how the listed node is connected to the source node degree?: number; parentContainers?: ParentContainersResult | null; - parentNodes?: ParentNodesResult | null; + parentEntities?: Entity[] | null; previewType?: Maybe; paths?: EntityPath[]; health?: Health[]; @@ -225,10 +227,11 @@ export default function DefaultPreviewCard({ titleSizePx, dataTestID, externalUrl, + entityTitleSuffix, onClick, degree, parentContainers, - parentNodes, + parentEntities, platforms, logoUrls, previewType, @@ -277,7 +280,7 @@ export default function DefaultPreviewCard({ typeIcon={typeIcon} entityType={type} parentContainers={parentContainers?.containers} - parentNodes={parentNodes?.nodes} + parentEntities={parentEntities} parentContainersRef={contentRef} areContainersTruncated={isContentTruncated} /> @@ -289,7 +292,7 @@ export default function DefaultPreviewCard({ ) : ( - {name || ' '} + )} @@ -305,6 +308,7 @@ export default function DefaultPreviewCard({ entityType={type} /> )} + {entityTitleSuffix} {degree !== undefined && degree !== null && ( ) : undefined } + customRender={(text) => } > {description} diff --git a/datahub-web-react/src/app/recommendations/renderer/component/DomainSearchList.tsx b/datahub-web-react/src/app/recommendations/renderer/component/DomainSearchList.tsx index d3cc35ef6a932b..c82521dab1bc9b 100644 --- a/datahub-web-react/src/app/recommendations/renderer/component/DomainSearchList.tsx +++ b/datahub-web-react/src/app/recommendations/renderer/component/DomainSearchList.tsx @@ -1,10 +1,14 @@ +import { ArrowRightOutlined } from '@ant-design/icons'; import React from 'react'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { Domain, EntityType, RecommendationContent } from '../../../../types.generated'; -import { IconStyleType } from '../../../entity/Entity'; import { LogoCountCard } from '../../../shared/LogoCountCard'; import { useEntityRegistry } from '../../../useEntityRegistry'; +import DomainIcon from '../../../domain/DomainIcon'; +import { PageRoutes } from '../../../../conf/Global'; +import { HomePageButton } from '../../../shared/components'; +import { HoverEntityTooltip } from './HoverEntityTooltip'; const DomainListContainer = styled.div` display: flex; @@ -13,6 +17,17 @@ const DomainListContainer = styled.div` flex-wrap: wrap; `; +const AllDomainsWrapper = styled.div` + color: ${(props) => props.theme.styles['primary-color']}; + font-size: 14px; +`; + +const AllDomainsText = styled.div` + margin-bottom: 8px; +`; + +const NUM_DOMAIN_CARDS = 9; + type Props = { content: Array; onClick?: (index: number) => void; @@ -23,7 +38,8 @@ export const DomainSearchList = ({ content, onClick }: Props) => { const domainsWithCounts: Array<{ domain: Domain; count?: number }> = content .map((cnt) => ({ domain: cnt.entity, count: cnt.params?.contentParams?.count })) - .filter((domainWithCount) => domainWithCount.domain !== null && domainWithCount !== undefined) as Array<{ + .filter((domainWithCount) => domainWithCount?.domain !== null) + .slice(0, NUM_DOMAIN_CARDS) as Array<{ domain: Domain; count?: number; }>; @@ -31,18 +47,34 @@ export const DomainSearchList = ({ content, onClick }: Props) => { return ( {domainsWithCounts.map((domain, index) => ( - onClick?.(index)} - > - - + + onClick?.(index)} + > + + } + count={domain.count} + /> + + ))} + + + + View All Domains + + + + ); }; diff --git a/datahub-web-react/src/app/recommendations/renderer/component/HoverEntityTooltip.tsx b/datahub-web-react/src/app/recommendations/renderer/component/HoverEntityTooltip.tsx index a39a39cd52db90..9ff0a1a2f940bf 100644 --- a/datahub-web-react/src/app/recommendations/renderer/component/HoverEntityTooltip.tsx +++ b/datahub-web-react/src/app/recommendations/renderer/component/HoverEntityTooltip.tsx @@ -1,3 +1,4 @@ +import { TooltipPlacement } from 'antd/es/tooltip'; import { Tooltip } from 'antd'; import React from 'react'; import { Entity } from '../../../../types.generated'; @@ -9,9 +10,10 @@ type Props = { // whether the tooltip can be opened or if it should always stay closed canOpen?: boolean; children: React.ReactNode; + placement?: TooltipPlacement; }; -export const HoverEntityTooltip = ({ entity, canOpen = true, children }: Props) => { +export const HoverEntityTooltip = ({ entity, canOpen = true, children, placement }: Props) => { const entityRegistry = useEntityRegistry(); if (!entity || !entity.type || !entity.urn) { @@ -23,7 +25,7 @@ export const HoverEntityTooltip = ({ entity, canOpen = true, children }: Props) {entityRegistry.renderPreview(entity.type, PreviewType.HOVER_CARD, entity)}} diff --git a/datahub-web-react/src/app/search/EmptySearchResults.tsx b/datahub-web-react/src/app/search/EmptySearchResults.tsx new file mode 100644 index 00000000000000..cde61f746d35bd --- /dev/null +++ b/datahub-web-react/src/app/search/EmptySearchResults.tsx @@ -0,0 +1,90 @@ +import { RocketOutlined } from '@ant-design/icons'; +import { useHistory } from 'react-router'; +import { Button } from 'antd'; +import React, { useCallback } from 'react'; +import styled from 'styled-components'; +import { ANTD_GRAY_V2 } from '../entity/shared/constants'; +import { navigateToSearchUrl } from './utils/navigateToSearchUrl'; +import analytics, { EventType } from '../analytics'; +import { SuggestedText } from './suggestions/SearchQuerySugggester'; +import useGetSearchQueryInputs from './useGetSearchQueryInputs'; +import { FacetFilterInput, SearchSuggestion } from '../../types.generated'; +import { useUserContext } from '../context/useUserContext'; + +const NoDataContainer = styled.div` + margin: 40px auto; + font-size: 16px; + color: ${ANTD_GRAY_V2[8]}; +`; + +const Section = styled.div` + margin-bottom: 16px; +`; + +function getRefineSearchText(filters: FacetFilterInput[], viewUrn?: string | null) { + let text = ''; + if (filters.length && viewUrn) { + text = 'clearing all filters and selected view'; + } else if (filters.length) { + text = 'clearing all filters'; + } else if (viewUrn) { + text = 'clearing the selected view'; + } + + return text; +} + +interface Props { + suggestions: SearchSuggestion[]; +} + +export default function EmptySearchResults({ suggestions }: Props) { + const { query, filters, viewUrn } = useGetSearchQueryInputs(); + const history = useHistory(); + const userContext = useUserContext(); + const suggestText = suggestions.length > 0 ? suggestions[0].text : ''; + const refineSearchText = getRefineSearchText(filters, viewUrn); + + const onClickExploreAll = useCallback(() => { + analytics.event({ type: EventType.SearchResultsExploreAllClickEvent }); + navigateToSearchUrl({ query: '*', history }); + }, [history]); + + const searchForSuggestion = () => { + navigateToSearchUrl({ query: suggestText, history }); + }; + + const clearFiltersAndView = () => { + navigateToSearchUrl({ query, history }); + userContext.updateLocalState({ + ...userContext.localState, + selectedViewUrn: undefined, + }); + }; + + return ( + +
No results found for "{query}"
+ {refineSearchText && ( + <> + Try {refineSearchText}{' '} + {suggestText && ( + <> + or searching for {suggestText} + + )} + + )} + {!refineSearchText && suggestText && ( + <> + Did you mean {suggestText} + + )} + {!refineSearchText && !suggestText && ( + + )} +
+ ); +} diff --git a/datahub-web-react/src/app/search/EntityGroupSearchResults.tsx b/datahub-web-react/src/app/search/EntityGroupSearchResults.tsx deleted file mode 100644 index 9b577048145c5e..00000000000000 --- a/datahub-web-react/src/app/search/EntityGroupSearchResults.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { ArrowRightOutlined } from '@ant-design/icons'; -import { Button, Card, Divider, List, Space, Typography } from 'antd'; -import { ListProps } from 'antd/lib/list'; -import * as React from 'react'; -import { useHistory } from 'react-router-dom'; -import styled from 'styled-components'; -import { EntityType, SearchResult } from '../../types.generated'; -import { IconStyleType } from '../entity/Entity'; -import { useEntityRegistry } from '../useEntityRegistry'; -import { navigateToSearchUrl } from './utils/navigateToSearchUrl'; -import analytics, { EventType } from '../analytics'; - -const styles = { - header: { marginBottom: 20 }, - resultHeaderCardBody: { padding: '16px 24px' }, - resultHeaderCard: { right: '52px', top: '-40px', position: 'absolute' }, - seeAllButton: { fontSize: 18 }, - resultsContainer: { width: '100%', padding: '40px 132px' }, -}; - -const ResultList = styled(List)` - &&& { - width: 100%; - border-color: ${(props) => props.theme.styles['border-color-base']}; - margin-top: 8px; - padding: 16px 48px; - box-shadow: ${(props) => props.theme.styles['box-shadow']}; - } -`; - -interface Props { - type: EntityType; - query: string; - searchResults: Array; -} - -export const EntityGroupSearchResults = ({ type, query, searchResults }: Props) => { - const history = useHistory(); - const entityRegistry = useEntityRegistry(); - - const onResultClick = (result: SearchResult, index: number) => { - analytics.event({ - type: EventType.SearchResultClickEvent, - query, - entityUrn: result.entity.urn, - entityType: result.entity.type, - index, - total: searchResults.length, - }); - }; - - return ( - - >> - header={ - - {entityRegistry.getCollectionName(type)} - - {entityRegistry.getIcon(type, 36, IconStyleType.ACCENT)} - - - } - footer={ - searchResults.length > 0 && ( - - ) - } - dataSource={searchResults as SearchResult[]} - split={false} - renderItem={(searchResult, index) => ( - <> - onResultClick(searchResult, index)}> - {entityRegistry.renderSearchResult(type, searchResult)} - - {index < searchResults.length - 1 && } - - )} - bordered - /> - - ); -}; diff --git a/datahub-web-react/src/app/search/PostLinkCard.tsx b/datahub-web-react/src/app/search/PostLinkCard.tsx index 04308632c61c96..2111c0b25ad848 100644 --- a/datahub-web-react/src/app/search/PostLinkCard.tsx +++ b/datahub-web-react/src/app/search/PostLinkCard.tsx @@ -39,12 +39,17 @@ const TextContainer = styled.div` flex: 2; `; -const TextWrapper = styled.div` - text-align: left; +const FlexWrapper = styled.div<{ alignCenter?: boolean }>` display: flex; flex-direction: column; justify-content: center; flex: 2; + ${(props) => props.alignCenter && 'align-items: center;'} +`; + +const TextWrapper = styled.div` + display: flex; + flex-direction: column; `; const HeaderText = styled(Typography.Text)` @@ -74,19 +79,21 @@ export const PostLinkCard = ({ linkPost }: Props) => { const link = linkPost?.content?.link || ''; return ( - + {hasMedia && ( )} - - Link - - {linkPost?.content?.title} - - + + + Link + + {linkPost?.content?.title} + + + diff --git a/datahub-web-react/src/app/search/PostTextCard.tsx b/datahub-web-react/src/app/search/PostTextCard.tsx index 1bba55425fe0d0..15b34e37fc01cb 100644 --- a/datahub-web-react/src/app/search/PostTextCard.tsx +++ b/datahub-web-react/src/app/search/PostTextCard.tsx @@ -7,7 +7,6 @@ import { Post } from '../../types.generated'; const CardContainer = styled.div` display: flex; flex-direction: row; - min-height: 140px; border: 1px solid ${ANTD_GRAY[4]}; border-radius: 12px; box-shadow: ${(props) => props.theme.styles['box-shadow']}; @@ -15,6 +14,7 @@ const CardContainer = styled.div` box-shadow: ${(props) => props.theme.styles['box-shadow-hover']}; } white-space: unset; + padding-bottom: 4px; `; const TextContainer = styled.div` @@ -28,6 +28,9 @@ const TextContainer = styled.div` const TitleText = styled(Typography.Title)` word-break: break-word; min-height: 20px; + &&& { + margin-top: 8px; + } `; const HeaderText = styled(Typography.Text)` diff --git a/datahub-web-react/src/app/search/SearchPage.tsx b/datahub-web-react/src/app/search/SearchPage.tsx index ce353640d81793..6387f0ef8c05ec 100644 --- a/datahub-web-react/src/app/search/SearchPage.tsx +++ b/datahub-web-react/src/app/search/SearchPage.tsx @@ -59,6 +59,7 @@ export const SearchPage = () => { orFilters, viewUrn, sortInput, + searchFlags: { getSuggestions: true }, }, }, }); @@ -235,6 +236,7 @@ export const SearchPage = () => { error={error} searchResponse={data?.searchAcrossEntities} facets={data?.searchAcrossEntities?.facets} + suggestions={data?.searchAcrossEntities?.suggestions || []} selectedFilters={filters} loading={loading} onChangeFilters={onChangeFilters} diff --git a/datahub-web-react/src/app/search/SearchResultList.tsx b/datahub-web-react/src/app/search/SearchResultList.tsx index 6e2d5c923c6e27..f8ca9a46d1a81a 100644 --- a/datahub-web-react/src/app/search/SearchResultList.tsx +++ b/datahub-web-react/src/app/search/SearchResultList.tsx @@ -1,18 +1,16 @@ -import React, { useCallback } from 'react'; -import { Button, Checkbox, Divider, Empty, List, ListProps } from 'antd'; +import React from 'react'; +import { Checkbox, Divider, List, ListProps } from 'antd'; import styled from 'styled-components'; -import { useHistory } from 'react-router'; -import { RocketOutlined } from '@ant-design/icons'; -import { navigateToSearchUrl } from './utils/navigateToSearchUrl'; import { ANTD_GRAY } from '../entity/shared/constants'; import { SEPARATE_SIBLINGS_URL_PARAM } from '../entity/shared/siblingUtils'; import { CompactEntityNameList } from '../recommendations/renderer/component/CompactEntityNameList'; import { useEntityRegistry } from '../useEntityRegistry'; -import { SearchResult } from '../../types.generated'; +import { SearchResult, SearchSuggestion } from '../../types.generated'; import analytics, { EventType } from '../analytics'; import { EntityAndType } from '../entity/shared/types'; import { useIsSearchV2 } from './useSearchAndBrowseVersion'; import { CombinedSearchResult } from './utils/combineSiblingsInSearchResults'; +import EmptySearchResults from './EmptySearchResults'; const ResultList = styled(List)` &&& { @@ -28,19 +26,12 @@ const StyledCheckbox = styled(Checkbox)` margin-right: 12px; `; -const NoDataContainer = styled.div` - > div { - margin-top: 28px; - margin-bottom: 28px; - } -`; - const ThinDivider = styled(Divider)` margin-top: 16px; margin-bottom: 16px; `; -const ResultWrapper = styled.div<{ showUpdatedStyles: boolean }>` +export const ResultWrapper = styled.div<{ showUpdatedStyles: boolean }>` ${(props) => props.showUpdatedStyles && ` @@ -48,7 +39,6 @@ const ResultWrapper = styled.div<{ showUpdatedStyles: boolean }>` border-radius: 5px; margin: 0 auto 8px auto; padding: 8px 16px; - max-width: 1200px; border-bottom: 1px solid ${ANTD_GRAY[5]}; `} `; @@ -70,6 +60,7 @@ type Props = { isSelectMode: boolean; selectedEntities: EntityAndType[]; setSelectedEntities: (entities: EntityAndType[]) => any; + suggestions: SearchSuggestion[]; }; export const SearchResultList = ({ @@ -79,17 +70,12 @@ export const SearchResultList = ({ isSelectMode, selectedEntities, setSelectedEntities, + suggestions, }: Props) => { - const history = useHistory(); const entityRegistry = useEntityRegistry(); const selectedEntityUrns = selectedEntities.map((entity) => entity.urn); const showSearchFiltersV2 = useIsSearchV2(); - const onClickExploreAll = useCallback(() => { - analytics.event({ type: EventType.SearchResultsExploreAllClickEvent }); - navigateToSearchUrl({ query: '*', history }); - }, [history]); - const onClickResult = (result: SearchResult, index: number) => { analytics.event({ type: EventType.SearchResultClickEvent, @@ -118,19 +104,7 @@ export const SearchResultList = ({ id="search-result-list" dataSource={searchResults} split={false} - locale={{ - emptyText: ( - - - - - ), - }} + locale={{ emptyText: }} renderItem={(item, index) => ( ` display: flex; @@ -54,7 +56,7 @@ const ResultContainer = styled.div<{ v2Styles: boolean }>` ? ` display: flex; flex-direction: column; - background-color: #F8F9FA; + background-color: ${ANTD_GRAY_V2[1]}; ` : ` max-width: calc(100% - 260px); @@ -131,6 +133,7 @@ interface Props { setNumResultsPerPage: (numResults: number) => void; isSelectMode: boolean; selectedEntities: EntityAndType[]; + suggestions: SearchSuggestion[]; setSelectedEntities: (entities: EntityAndType[]) => void; setIsSelectMode: (showSelectMode: boolean) => any; onChangeSelectAll: (selected: boolean) => void; @@ -155,6 +158,7 @@ export const SearchResults = ({ setNumResultsPerPage, isSelectMode, selectedEntities, + suggestions, setIsSelectMode, setSelectedEntities, onChangeSelectAll, @@ -238,6 +242,7 @@ export const SearchResults = ({ {(error && ) || (!loading && ( + {totalResults > 0 && } - - SearchCfg.RESULTS_PER_PAGE} - onShowSizeChange={(_currNum, newNum) => setNumResultsPerPage(newNum)} - pageSizeOptions={['10', '20', '50', '100']} - /> - + {totalResults > 0 && ( + + SearchCfg.RESULTS_PER_PAGE} + onShowSizeChange={(_currNum, newNum) => setNumResultsPerPage(newNum)} + pageSizeOptions={['10', '20', '50', '100']} + /> + + )} {authenticatedUserUrn && ( 0; return ( @@ -95,6 +99,7 @@ export default function AutoCompleteEntity({ query, entity, siblings, hasParentT {showPlatforms && } {showPlatformDivider && } {showParentContainers && } + )} void; }; export const DEFAULT_CONTEXT = { + query: undefined, selectedSortOption: undefined, setSelectedSortOption: (_: string) => null, }; @@ -21,3 +23,7 @@ export function useSearchContext() { export function useSelectedSortOption() { return useSearchContext().selectedSortOption; } + +export function useSearchQuery() { + return useSearchContext().query; +} diff --git a/datahub-web-react/src/app/search/context/SearchContextProvider.tsx b/datahub-web-react/src/app/search/context/SearchContextProvider.tsx index bfb65c1d74d3ee..5ad9667ab1fc09 100644 --- a/datahub-web-react/src/app/search/context/SearchContextProvider.tsx +++ b/datahub-web-react/src/app/search/context/SearchContextProvider.tsx @@ -8,6 +8,7 @@ export default function SearchContextProvider({ children }: { children: React.Re const history = useHistory(); const location = useLocation(); const params = useMemo(() => QueryString.parse(location.search, { arrayFormat: 'comma' }), [location.search]); + const query = (params.query ? decodeURIComponent(params.query as string) : undefined) as string | undefined; const selectedSortOption = params.sortOption as string | undefined; function setSelectedSortOption(selectedOption: string) { @@ -15,7 +16,7 @@ export default function SearchContextProvider({ children }: { children: React.Re } return ( - + {children} ); diff --git a/datahub-web-react/src/app/search/context/SearchResultContext.tsx b/datahub-web-react/src/app/search/context/SearchResultContext.tsx new file mode 100644 index 00000000000000..68adead0051492 --- /dev/null +++ b/datahub-web-react/src/app/search/context/SearchResultContext.tsx @@ -0,0 +1,72 @@ +import React, { ReactNode, createContext, useContext, useMemo } from 'react'; +import { SearchResult } from '../../../types.generated'; +import { + getMatchedFieldsByUrn, + getMatchedFieldNames, + getMatchedFieldsByNames, + shouldShowInMatchedFieldList, + getMatchedFieldLabel, + getMatchesPrioritized, +} from '../matches/utils'; +import { MatchedFieldName } from '../matches/constants'; + +type SearchResultContextValue = { + searchResult: SearchResult; +} | null; + +const SearchResultContext = createContext(null); + +type Props = { + children: ReactNode; + searchResult: SearchResult; +}; + +export const SearchResultProvider = ({ children, searchResult }: Props) => { + const value = useMemo( + () => ({ + searchResult, + }), + [searchResult], + ); + return {children}; +}; + +const useSearchResultContext = () => { + return useContext(SearchResultContext); +}; + +export const useSearchResult = () => { + return useSearchResultContext()?.searchResult; +}; + +export const useEntityType = () => { + return useSearchResultContext()?.searchResult.entity.type; +}; + +export const useMatchedFields = () => { + return useSearchResult()?.matchedFields ?? []; +}; + +export const useMatchedFieldsForList = (primaryField: MatchedFieldName) => { + const entityType = useEntityType(); + const matchedFields = useMatchedFields(); + const showableFields = matchedFields.filter((field) => shouldShowInMatchedFieldList(entityType, field)); + return entityType ? getMatchesPrioritized(entityType, showableFields, primaryField) : []; +}; + +export const useMatchedFieldsByGroup = (fieldName: MatchedFieldName) => { + const entityType = useEntityType(); + const matchedFields = useMatchedFields(); + const matchedFieldNames = getMatchedFieldNames(entityType, fieldName); + return getMatchedFieldsByNames(matchedFields, matchedFieldNames); +}; + +export const useHasMatchedFieldByUrn = (urn: string, fieldName: MatchedFieldName) => { + const matchedFields = useMatchedFieldsByGroup(fieldName); + return getMatchedFieldsByUrn(matchedFields, urn).length > 0; +}; + +export const useMatchedFieldLabel = (fieldName: string) => { + const entityType = useEntityType(); + return getMatchedFieldLabel(entityType, fieldName); +}; diff --git a/datahub-web-react/src/app/search/context/constants.ts b/datahub-web-react/src/app/search/context/constants.ts index 372230db023e9d..5f841b8536e196 100644 --- a/datahub-web-react/src/app/search/context/constants.ts +++ b/datahub-web-react/src/app/search/context/constants.ts @@ -1,15 +1,23 @@ import { SortOrder } from '../../../types.generated'; export const RELEVANCE = 'relevance'; -export const NAME_FIELD = 'name'; +export const ENTITY_NAME_FIELD = '_entityName'; export const LAST_OPERATION_TIME_FIELD = 'lastOperationTime'; export const DEFAULT_SORT_OPTION = RELEVANCE; export const SORT_OPTIONS = { [RELEVANCE]: { label: 'Relevance', field: RELEVANCE, sortOrder: SortOrder.Descending }, - [`${NAME_FIELD}_${SortOrder.Ascending}`]: { label: 'A to Z', field: NAME_FIELD, sortOrder: SortOrder.Ascending }, - [`${NAME_FIELD}_${SortOrder.Descending}`]: { label: 'Z to A', field: NAME_FIELD, sortOrder: SortOrder.Descending }, + [`${ENTITY_NAME_FIELD}_${SortOrder.Ascending}`]: { + label: 'A to Z', + field: ENTITY_NAME_FIELD, + sortOrder: SortOrder.Ascending, + }, + [`${ENTITY_NAME_FIELD}_${SortOrder.Descending}`]: { + label: 'Z to A', + field: ENTITY_NAME_FIELD, + sortOrder: SortOrder.Descending, + }, [`${LAST_OPERATION_TIME_FIELD}_${SortOrder.Descending}`]: { label: 'Last Modified in Platform', field: LAST_OPERATION_TIME_FIELD, diff --git a/datahub-web-react/src/app/search/filters/FilterOption.tsx b/datahub-web-react/src/app/search/filters/FilterOption.tsx index b112413efd845d..0a3ea3822763e3 100644 --- a/datahub-web-react/src/app/search/filters/FilterOption.tsx +++ b/datahub-web-react/src/app/search/filters/FilterOption.tsx @@ -3,7 +3,7 @@ import { Button, Checkbox } from 'antd'; import React, { useState } from 'react'; import styled from 'styled-components'; import { FilterOptionType } from './types'; -import { EntityType, GlossaryNode, GlossaryTerm, Tag } from '../../../types.generated'; +import { Entity, EntityType, Tag } from '../../../types.generated'; import { generateColor } from '../../entity/shared/components/styled/StyledTag'; import { ANTD_GRAY } from '../../entity/shared/constants'; import { useEntityRegistry } from '../../useEntityRegistry'; @@ -15,9 +15,9 @@ import { TYPE_NAMES_FILTER_NAME, } from '../utils/constants'; import { IconSpacer, Label } from './ActiveFilter'; -import { isFilterOptionSelected, getFilterIconAndLabel, isAnyOptionSelected } from './utils'; +import { isFilterOptionSelected, getFilterIconAndLabel, isAnyOptionSelected, getParentEntities } from './utils'; import { capitalizeFirstLetterOnly } from '../../shared/textUtil'; -import ParentNodes from './ParentNodes'; +import ParentEntities from './ParentEntities'; import { formatNumber } from '../../shared/formatNumber'; const FilterOptionWrapper = styled.div<{ centerAlign?: boolean; addPadding?: boolean }>` @@ -102,6 +102,10 @@ const ArrowButton = styled(Button)<{ isOpen: boolean }>` `} `; +const ParentWrapper = styled.div` + max-width: 220px; +`; + interface Props { filterOption: FilterOptionType; selectedFilterOptions: FilterOptionType[]; @@ -124,8 +128,7 @@ export default function FilterOption({ const shouldShowIcon = field === PLATFORM_FILTER_NAME && icon !== null; const shouldShowTagColor = field === TAGS_FILTER_NAME && entity?.type === EntityType.Tag; const isSubTypeFilter = field === TYPE_NAMES_FILTER_NAME; - const isGlossaryTerm = entity?.type === EntityType.GlossaryTerm; - const parentNodes: GlossaryNode[] = isGlossaryTerm ? (entity as GlossaryTerm).parentNodes?.nodes || [] : []; + const parentEntities: Entity[] = getParentEntities(entity as Entity) || []; // only entity type filters return 10,000 max aggs const countText = count === MAX_COUNT_VAL && field === ENTITY_SUB_TYPE_FILTER_NAME ? '10k+' : formatNumber(count); @@ -143,7 +146,7 @@ export default function FilterOption({ return ( <> - 0} addPadding={addPadding}> + 0} addPadding={addPadding}> - {isGlossaryTerm && } + {parentEntities.length > 0 && ( + + + + )} {shouldShowIcon && <>{icon}} {shouldShowTagColor && ( diff --git a/datahub-web-react/src/app/search/filters/ParentNodes.tsx b/datahub-web-react/src/app/search/filters/ParentEntities.tsx similarity index 54% rename from datahub-web-react/src/app/search/filters/ParentNodes.tsx rename to datahub-web-react/src/app/search/filters/ParentEntities.tsx index 7012f07c16e64c..2504d5f0ff25a1 100644 --- a/datahub-web-react/src/app/search/filters/ParentNodes.tsx +++ b/datahub-web-react/src/app/search/filters/ParentEntities.tsx @@ -2,19 +2,16 @@ import { FolderOpenOutlined } from '@ant-design/icons'; import { Tooltip, Typography } from 'antd'; import React from 'react'; import styled from 'styled-components'; -import { EntityType, GlossaryNode, GlossaryTerm } from '../../../types.generated'; +import { Entity } from '../../../types.generated'; import { ANTD_GRAY } from '../../entity/shared/constants'; import { useEntityRegistry } from '../../useEntityRegistry'; -const NUM_VISIBLE_NODES = 2; - const ParentNodesWrapper = styled.div` font-size: 12px; color: ${ANTD_GRAY[7]}; display: flex; align-items: center; margin-bottom: 3px; - max-width: 220px; overflow: hidden; `; @@ -27,54 +24,62 @@ export const ArrowWrapper = styled.span` margin: 0 3px; `; +const StyledTooltip = styled(Tooltip)` + display: flex; + white-space: nowrap; + overflow: hidden; +`; + +const DEFAULT_NUM_VISIBLE = 2; + interface Props { - glossaryTerm: GlossaryTerm; + parentEntities: Entity[]; + numVisible?: number; } -export default function ParentNodes({ glossaryTerm }: Props) { +export default function ParentEntities({ parentEntities, numVisible = DEFAULT_NUM_VISIBLE }: Props) { const entityRegistry = useEntityRegistry(); - const parentNodes: GlossaryNode[] = glossaryTerm.parentNodes?.nodes || []; - // parent nodes are returned with direct parent first - const orderedParentNodes = [...parentNodes].reverse(); - const visibleNodes = orderedParentNodes.slice(orderedParentNodes.length - NUM_VISIBLE_NODES); - const numHiddenNodes = orderedParentNodes.length - NUM_VISIBLE_NODES; - const includeNodePathTooltip = parentNodes.length > NUM_VISIBLE_NODES; + // parent nodes/domains are returned with direct parent first + const orderedParentEntities = [...parentEntities].reverse(); + const numHiddenEntities = orderedParentEntities.length - numVisible; + const hasHiddenEntities = numHiddenEntities > 0; + const visibleNodes = hasHiddenEntities ? orderedParentEntities.slice(numHiddenEntities) : orderedParentEntities; - if (!parentNodes.length) return null; + if (!parentEntities.length) return null; return ( - - {orderedParentNodes.map((glossaryNode, index) => ( + {orderedParentEntities.map((parentEntity, index) => ( <> - {entityRegistry.getDisplayName(EntityType.GlossaryNode, glossaryNode)} + {entityRegistry.getDisplayName(parentEntity.type, parentEntity)} - {index !== orderedParentNodes.length - 1 && {'>'}} + {index !== orderedParentEntities.length - 1 && {'>'}} ))} } > - {numHiddenNodes > 0 && - [...Array(numHiddenNodes)].map(() => ( + {hasHiddenEntities && + [...Array(numHiddenEntities)].map(() => ( <> {'>'} ))} - {visibleNodes.map((glossaryNode, index) => { - const displayName = entityRegistry.getDisplayName(EntityType.GlossaryNode, glossaryNode); + {visibleNodes.map((parentEntity, index) => { + const displayName = entityRegistry.getDisplayName(parentEntity.type, parentEntity); return ( <> - + {displayName} {index !== visibleNodes.length - 1 && {'>'}} @@ -82,6 +87,6 @@ export default function ParentNodes({ glossaryTerm }: Props) { ); })} - + ); } diff --git a/datahub-web-react/src/app/search/filters/utils.tsx b/datahub-web-react/src/app/search/filters/utils.tsx index fbde71d6a2e9a8..6ea9d0e8baa4f3 100644 --- a/datahub-web-react/src/app/search/filters/utils.tsx +++ b/datahub-web-react/src/app/search/filters/utils.tsx @@ -14,10 +14,12 @@ import { AggregationMetadata, DataPlatform, DataPlatformInstance, + Domain, Entity, EntityType, FacetFilterInput, FacetMetadata, + GlossaryTerm, } from '../../../types.generated'; import { IconStyleType } from '../../entity/Entity'; import { @@ -331,3 +333,16 @@ export function canCreateViewFromFilters(activeFilters: FacetFilterInput[]) { } return true; } + +export function getParentEntities(entity: Entity): Entity[] | null { + if (!entity) { + return null; + } + if (entity.type === EntityType.GlossaryTerm) { + return (entity as GlossaryTerm).parentNodes?.nodes || []; + } + if (entity.type === EntityType.Domain) { + return (entity as Domain).parentDomains?.domains || []; + } + return null; +} diff --git a/datahub-web-react/src/app/search/matches/MatchedFieldList.tsx b/datahub-web-react/src/app/search/matches/MatchedFieldList.tsx new file mode 100644 index 00000000000000..0bfe000dea3663 --- /dev/null +++ b/datahub-web-react/src/app/search/matches/MatchedFieldList.tsx @@ -0,0 +1,133 @@ +import React from 'react'; + +import { Tooltip, Typography } from 'antd'; +import styled from 'styled-components'; +import { useMatchedFieldLabel, useMatchedFieldsForList } from '../context/SearchResultContext'; +import { MatchedField } from '../../../types.generated'; +import { ANTD_GRAY_V2 } from '../../entity/shared/constants'; +import { useSearchQuery } from '../context/SearchContext'; +import { MatchesGroupedByFieldName } from './constants'; +import { useEntityRegistry } from '../../useEntityRegistry'; +import { getDescriptionSlice, isDescriptionField, isHighlightableEntityField } from './utils'; + +const MatchesContainer = styled.div` + display: flex; + flex-wrap: wrap; + gap: 8px; +`; + +const MatchText = styled(Typography.Text)` + color: ${ANTD_GRAY_V2[8]}; + background: ${(props) => props.theme.styles['highlight-color']}; + border-radius: 4px; + padding: 2px 4px 2px 4px; + padding-right: 4px; +`; + +const MATCH_GROUP_LIMIT = 3; +const TOOLTIP_MATCH_GROUP_LIMIT = 10; + +type CustomFieldRenderer = (field: MatchedField) => JSX.Element | null; + +type Props = { + customFieldRenderer?: CustomFieldRenderer; + matchSuffix?: string; +}; + +const RenderedField = ({ + customFieldRenderer, + field, +}: { + customFieldRenderer?: CustomFieldRenderer; + field: MatchedField; +}) => { + const entityRegistry = useEntityRegistry(); + const query = useSearchQuery()?.trim().toLowerCase(); + const customRenderedField = customFieldRenderer?.(field); + if (customRenderedField) return {customRenderedField}; + if (isHighlightableEntityField(field)) { + return field.entity ? <>{entityRegistry.getDisplayName(field.entity.type, field.entity)} : <>; + } + if (isDescriptionField(field) && query) return {getDescriptionSlice(field.value, query)}; + return {field.value}; +}; + +const MatchedFieldsList = ({ + groupedMatch, + limit, + tooltip, + matchSuffix = '', + customFieldRenderer, +}: { + groupedMatch: MatchesGroupedByFieldName; + limit: number; + tooltip?: JSX.Element; + matchSuffix?: string; + customFieldRenderer?: CustomFieldRenderer; +}) => { + const label = useMatchedFieldLabel(groupedMatch.fieldName); + const count = groupedMatch.matchedFields.length; + const moreCount = Math.max(count - limit, 0); + const andMore = ( + <> + {' '} + & more + + ); + return ( + <> + Matches {count > 1 && `${count} `} + {label} + {count > 1 && 's'}{' '} + {groupedMatch.matchedFields.slice(0, limit).map((field, index) => ( + <> + {index > 0 && ', '} + <> + + + + ))} + {moreCount > 0 && + (tooltip ? ( + + {andMore} + + ) : ( + <>{andMore} + ))}{' '} + {matchSuffix} + + ); +}; + +export const MatchedFieldList = ({ customFieldRenderer, matchSuffix = '' }: Props) => { + const groupedMatches = useMatchedFieldsForList('fieldLabels'); + + return ( + <> + {groupedMatches.length > 0 ? ( + + {groupedMatches.map((groupedMatch) => { + return ( + + + } + /> + + ); + })} + + ) : null} + + ); +}; diff --git a/datahub-web-react/src/app/search/matches/SearchTextHighlighter.tsx b/datahub-web-react/src/app/search/matches/SearchTextHighlighter.tsx new file mode 100644 index 00000000000000..d8da1088ea89d1 --- /dev/null +++ b/datahub-web-react/src/app/search/matches/SearchTextHighlighter.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import Highlight from 'react-highlighter'; +import styled from 'styled-components'; +import { useMatchedFieldsByGroup } from '../context/SearchResultContext'; +import { useSearchQuery } from '../context/SearchContext'; +import { MatchedFieldName } from './constants'; +import { useAppConfig } from '../../useAppConfig'; + +type Props = { + field: MatchedFieldName; + text: string; + enableFullHighlight?: boolean; +}; + +const HIGHLIGHT_ALL_PATTERN = /.*/; + +const StyledHighlight = styled(Highlight).attrs((props) => ({ + matchStyle: { background: props.theme.styles['highlight-color'] }, +}))``; + +const SearchTextHighlighter = ({ field, text, enableFullHighlight = false }: Props) => { + const appConfig = useAppConfig(); + const enableNameHighlight = appConfig.config.visualConfig.searchResult?.enableNameHighlight; + const matchedFields = useMatchedFieldsByGroup(field); + const hasMatchedField = !!matchedFields?.length; + const normalizedSearchQuery = useSearchQuery()?.trim().toLowerCase(); + const normalizedText = text.trim().toLowerCase(); + const hasSubstring = hasMatchedField && !!normalizedSearchQuery && normalizedText.includes(normalizedSearchQuery); + const pattern = enableFullHighlight ? HIGHLIGHT_ALL_PATTERN : undefined; + + return ( + <> + {enableNameHighlight && hasMatchedField ? ( + {text} + ) : ( + text + )} + + ); +}; + +export default SearchTextHighlighter; diff --git a/datahub-web-react/src/app/search/matches/constants.ts b/datahub-web-react/src/app/search/matches/constants.ts new file mode 100644 index 00000000000000..25ca82eef95978 --- /dev/null +++ b/datahub-web-react/src/app/search/matches/constants.ts @@ -0,0 +1,129 @@ +import { EntityType, MatchedField } from '../../../types.generated'; + +export type MatchedFieldName = + | 'urn' + | 'name' + | 'displayName' + | 'title' + | 'description' + | 'editedDescription' + | 'editedFieldDescriptions' + | 'fieldDescriptions' + | 'tags' + | 'fieldTags' + | 'editedFieldTags' + | 'glossaryTerms' + | 'fieldGlossaryTerms' + | 'editedFieldGlossaryTerms' + | 'fieldLabels' + | 'fieldPaths'; + +export type MatchedFieldConfig = { + name: MatchedFieldName; + groupInto?: MatchedFieldName; + label: string; + showInMatchedFieldList?: boolean; +}; + +const DEFAULT_MATCHED_FIELD_CONFIG: Array = [ + { + name: 'urn', + label: 'urn', + }, + { + name: 'title', + label: 'title', + }, + { + name: 'displayName', + groupInto: 'name', + label: 'display name', + }, + { + name: 'name', + groupInto: 'name', + label: 'name', + }, + { + name: 'editedDescription', + groupInto: 'description', + label: 'description', + }, + { + name: 'description', + groupInto: 'description', + label: 'description', + }, + { + name: 'editedFieldDescriptions', + groupInto: 'fieldDescriptions', + label: 'column description', + showInMatchedFieldList: true, + }, + { + name: 'fieldDescriptions', + groupInto: 'fieldDescriptions', + label: 'column description', + showInMatchedFieldList: true, + }, + { + name: 'tags', + label: 'tag', + }, + { + name: 'editedFieldTags', + groupInto: 'fieldTags', + label: 'column tag', + showInMatchedFieldList: true, + }, + { + name: 'fieldTags', + groupInto: 'fieldTags', + label: 'column tag', + showInMatchedFieldList: true, + }, + { + name: 'glossaryTerms', + label: 'term', + }, + { + name: 'editedFieldGlossaryTerms', + groupInto: 'fieldGlossaryTerms', + label: 'column term', + showInMatchedFieldList: true, + }, + { + name: 'fieldGlossaryTerms', + groupInto: 'fieldGlossaryTerms', + label: 'column term', + showInMatchedFieldList: true, + }, + { + name: 'fieldLabels', + label: 'label', + showInMatchedFieldList: true, + }, + { + name: 'fieldPaths', + label: 'column', + showInMatchedFieldList: true, + }, +]; + +export const CHART_DASHBOARD_FIELD_CONFIG: Array = DEFAULT_MATCHED_FIELD_CONFIG.map((config) => { + if (config.name === 'title') return { ...config, groupInto: 'name' }; + return config; +}); + +export const MATCHED_FIELD_CONFIG = { + [EntityType.Chart]: CHART_DASHBOARD_FIELD_CONFIG, + [EntityType.Dashboard]: CHART_DASHBOARD_FIELD_CONFIG, + DEFAULT: DEFAULT_MATCHED_FIELD_CONFIG, +} as const; + +export type MatchesGroupedByFieldName = { + fieldName: string; + matchedFields: Array; +}; + +export const HIGHLIGHTABLE_ENTITY_TYPES = [EntityType.Tag, EntityType.GlossaryTerm]; diff --git a/datahub-web-react/src/app/search/matches/matchedFieldPathsRenderer.tsx b/datahub-web-react/src/app/search/matches/matchedFieldPathsRenderer.tsx new file mode 100644 index 00000000000000..0a33530552864f --- /dev/null +++ b/datahub-web-react/src/app/search/matches/matchedFieldPathsRenderer.tsx @@ -0,0 +1,8 @@ +import React from 'react'; + +import { MatchedField } from '../../../types.generated'; +import { downgradeV2FieldPath } from '../../entity/dataset/profile/schema/utils/utils'; + +export const matchedFieldPathsRenderer = (matchedField: MatchedField) => { + return matchedField?.name === 'fieldPaths' ? {downgradeV2FieldPath(matchedField.value)} : null; +}; diff --git a/datahub-web-react/src/app/search/matches/matchedInputFieldRenderer.tsx b/datahub-web-react/src/app/search/matches/matchedInputFieldRenderer.tsx new file mode 100644 index 00000000000000..25634c9e8b80e7 --- /dev/null +++ b/datahub-web-react/src/app/search/matches/matchedInputFieldRenderer.tsx @@ -0,0 +1,40 @@ +import React from 'react'; + +import { Chart, Dashboard, EntityType, GlossaryTerm, MatchedField } from '../../../types.generated'; +import { useEntityRegistry } from '../../useEntityRegistry'; + +const LABEL_INDEX_NAME = 'fieldLabels'; +const TYPE_PROPERTY_KEY_NAME = 'type'; + +const TermName = ({ term }: { term: GlossaryTerm }) => { + const entityRegistry = useEntityRegistry(); + return <>{entityRegistry.getDisplayName(EntityType.GlossaryTerm, term)}; +}; + +export const matchedInputFieldRenderer = (matchedField: MatchedField, entity: Chart | Dashboard) => { + if (matchedField?.name === LABEL_INDEX_NAME) { + const matchedSchemaField = entity.inputFields?.fields?.find( + (field) => field?.schemaField?.label === matchedField.value, + ); + const matchedGlossaryTerm = matchedSchemaField?.schemaField?.glossaryTerms?.terms?.find( + (term) => term?.term?.name === matchedField.value, + ); + + if (matchedGlossaryTerm) { + let termType = 'term'; + const typeProperty = matchedGlossaryTerm.term.properties?.customProperties?.find( + (property) => property.key === TYPE_PROPERTY_KEY_NAME, + ); + if (typeProperty) { + termType = typeProperty.value || termType; + } + + return ( + <> + {termType} + + ); + } + } + return null; +}; diff --git a/datahub-web-react/src/app/search/matches/utils.test.ts b/datahub-web-react/src/app/search/matches/utils.test.ts new file mode 100644 index 00000000000000..8b5ed27f5c2ad6 --- /dev/null +++ b/datahub-web-react/src/app/search/matches/utils.test.ts @@ -0,0 +1,110 @@ +import { EntityType } from '../../../types.generated'; +import { getMatchesPrioritized } from './utils'; + +const mapping = new Map(); +mapping.set('fieldPaths', 'column'); +mapping.set('fieldDescriptions', 'column description'); +mapping.set('fieldTags', 'column tag'); + +const MOCK_MATCHED_FIELDS = [ + { + name: 'fieldPaths', + value: 'rain', + }, + { + name: 'fieldDescriptions', + value: 'rainbow', + }, + { + name: 'fieldPaths', + value: 'rainbow', + }, + { + name: 'fieldPaths', + value: 'rainbows', + }, +]; + +const MOCK_MATCHED_DESCRIPTION_FIELDS = [ + { + name: 'editedDescription', + value: 'edited description value', + }, + { + name: 'description', + value: 'description value', + }, + { + name: 'fieldDescriptions', + value: 'field descriptions value', + }, + { + name: 'editedFieldDescriptions', + value: 'edited field descriptions value', + }, +]; + +describe('utils', () => { + describe('getMatchPrioritizingPrimary', () => { + it('prioritizes exact match', () => { + global.window.location.search = 'query=rainbow'; + const groupedMatches = getMatchesPrioritized(EntityType.Dataset, MOCK_MATCHED_FIELDS, 'fieldPaths'); + expect(groupedMatches).toEqual([ + { + fieldName: 'fieldPaths', + matchedFields: [ + { name: 'fieldPaths', value: 'rainbow' }, + { name: 'fieldPaths', value: 'rainbows' }, + { name: 'fieldPaths', value: 'rain' }, + ], + }, + { + fieldName: 'fieldDescriptions', + matchedFields: [{ name: 'fieldDescriptions', value: 'rainbow' }], + }, + ]); + }); + it('will accept first contains match', () => { + global.window.location.search = 'query=bow'; + const groupedMatches = getMatchesPrioritized(EntityType.Dataset, MOCK_MATCHED_FIELDS, 'fieldPaths'); + expect(groupedMatches).toEqual([ + { + fieldName: 'fieldPaths', + matchedFields: [ + { name: 'fieldPaths', value: 'rainbow' }, + { name: 'fieldPaths', value: 'rainbows' }, + { name: 'fieldPaths', value: 'rain' }, + ], + }, + { + fieldName: 'fieldDescriptions', + matchedFields: [{ name: 'fieldDescriptions', value: 'rainbow' }], + }, + ]); + }); + it('will group by field name', () => { + global.window.location.search = ''; + const groupedMatches = getMatchesPrioritized( + EntityType.Dataset, + MOCK_MATCHED_DESCRIPTION_FIELDS, + 'fieldPaths', + ); + expect(groupedMatches).toEqual([ + { + fieldName: 'description', + matchedFields: [ + { name: 'editedDescription', value: 'edited description value' }, + { name: 'description', value: 'description value' }, + ], + }, + { + fieldName: 'fieldDescriptions', + matchedFields: [ + { name: 'fieldDescriptions', value: 'field descriptions value' }, + { name: 'editedFieldDescriptions', value: 'edited field descriptions value' }, + ], + }, + ]); + }); + }); +}); diff --git a/datahub-web-react/src/app/search/matches/utils.ts b/datahub-web-react/src/app/search/matches/utils.ts new file mode 100644 index 00000000000000..78c62f7eef4588 --- /dev/null +++ b/datahub-web-react/src/app/search/matches/utils.ts @@ -0,0 +1,136 @@ +import * as QueryString from 'query-string'; +import { EntityType, MatchedField } from '../../../types.generated'; +import { + HIGHLIGHTABLE_ENTITY_TYPES, + MATCHED_FIELD_CONFIG, + MatchedFieldConfig, + MatchedFieldName, + MatchesGroupedByFieldName, +} from './constants'; + +const getFieldConfigsByEntityType = (entityType: EntityType | undefined): Array => { + return entityType && entityType in MATCHED_FIELD_CONFIG + ? MATCHED_FIELD_CONFIG[entityType] + : MATCHED_FIELD_CONFIG.DEFAULT; +}; + +export const shouldShowInMatchedFieldList = (entityType: EntityType | undefined, field: MatchedField): boolean => { + const configs = getFieldConfigsByEntityType(entityType); + return configs.some((config) => config.name === field.name && config.showInMatchedFieldList); +}; + +export const getMatchedFieldLabel = (entityType: EntityType | undefined, fieldName: string): string => { + const configs = getFieldConfigsByEntityType(entityType); + return configs.find((config) => config.name === fieldName)?.label ?? ''; +}; + +export const getGroupedFieldName = ( + entityType: EntityType | undefined, + fieldName: string, +): MatchedFieldName | undefined => { + const configs = getFieldConfigsByEntityType(entityType); + const fieldConfig = configs.find((config) => config.name === fieldName); + return fieldConfig?.groupInto; +}; + +export const getMatchedFieldNames = ( + entityType: EntityType | undefined, + fieldName: MatchedFieldName, +): Array => { + return getFieldConfigsByEntityType(entityType) + .filter((config) => fieldName === config.groupInto || fieldName === config.name) + .map((field) => field.name); +}; + +export const getMatchedFieldsByNames = (fields: Array, names: Array): Array => { + return fields.filter((field) => names.includes(field.name)); +}; + +export const getMatchedFieldsByUrn = (fields: Array, urn: string): Array => { + return fields.filter((field) => field.value === urn); +}; + +function normalize(value: string) { + return value.trim().toLowerCase(); +} + +function fromQueryGetBestMatch( + selectedMatchedFields: MatchedField[], + rawQuery: string, + prioritizedField: string, +): Array { + const query = normalize(rawQuery); + const priorityMatches: Array = selectedMatchedFields.filter( + (field) => field.name === prioritizedField, + ); + const nonPriorityMatches: Array = selectedMatchedFields.filter( + (field) => field.name !== prioritizedField, + ); + const exactMatches: Array = []; + const containedMatches: Array = []; + const rest: Array = []; + + [...priorityMatches, ...nonPriorityMatches].forEach((field) => { + const normalizedValue = normalize(field.value); + if (normalizedValue === query) exactMatches.push(field); + else if (normalizedValue.includes(query)) containedMatches.push(field); + else rest.push(field); + }); + + return [...exactMatches, ...containedMatches, ...rest]; +} + +const getMatchesGroupedByFieldName = ( + entityType: EntityType, + matchedFields: Array, +): Array => { + const fieldNameToMatches = new Map>(); + const fieldNames: Array = []; + matchedFields.forEach((field) => { + const groupedFieldName = getGroupedFieldName(entityType, field.name) || field.name; + const matchesInMap = fieldNameToMatches.get(groupedFieldName); + if (matchesInMap) { + matchesInMap.push(field); + } else { + fieldNameToMatches.set(groupedFieldName, [field]); + fieldNames.push(groupedFieldName); + } + }); + return fieldNames.map((fieldName) => ({ + fieldName, + matchedFields: fieldNameToMatches.get(fieldName) ?? [], + })); +}; + +export const getMatchesPrioritized = ( + entityType: EntityType, + matchedFields: MatchedField[], + prioritizedField: string, +): Array => { + const { location } = window; + const params = QueryString.parse(location.search, { arrayFormat: 'comma' }); + const query: string = decodeURIComponent(params.query ? (params.query as string) : ''); + const matches = fromQueryGetBestMatch(matchedFields, query, prioritizedField); + return getMatchesGroupedByFieldName(entityType, matches); +}; + +export const isHighlightableEntityField = (field: MatchedField) => + !!field.entity && HIGHLIGHTABLE_ENTITY_TYPES.includes(field.entity.type); + +export const isDescriptionField = (field: MatchedField) => field.name.toLowerCase().includes('description'); + +const SURROUNDING_DESCRIPTION_CHARS = 10; +const MAX_DESCRIPTION_CHARS = 50; + +export const getDescriptionSlice = (text: string, target: string) => { + const queryIndex = text.indexOf(target); + const start = Math.max(0, queryIndex - SURROUNDING_DESCRIPTION_CHARS); + const end = Math.min( + start + MAX_DESCRIPTION_CHARS, + text.length, + queryIndex + target.length + SURROUNDING_DESCRIPTION_CHARS, + ); + const startEllipsis = start > 0 ? '...' : ''; + const endEllipsis = end < text.length ? '...' : ''; + return `${startEllipsis}${text.slice(start, end)}${endEllipsis}`; +}; diff --git a/datahub-web-react/src/app/search/sidebar/BrowseSidebar.tsx b/datahub-web-react/src/app/search/sidebar/BrowseSidebar.tsx index b5e9272cc5273a..0d3d40c4a71af8 100644 --- a/datahub-web-react/src/app/search/sidebar/BrowseSidebar.tsx +++ b/datahub-web-react/src/app/search/sidebar/BrowseSidebar.tsx @@ -6,13 +6,14 @@ import { BrowseProvider } from './BrowseContext'; import SidebarLoadingError from './SidebarLoadingError'; import { SEARCH_RESULTS_BROWSE_SIDEBAR_ID } from '../../onboarding/config/SearchOnboardingConfig'; import useSidebarEntities from './useSidebarEntities'; +import { ANTD_GRAY_V2 } from '../../entity/shared/constants'; const Sidebar = styled.div<{ visible: boolean; width: number }>` height: 100%; width: ${(props) => (props.visible ? `${props.width}px` : '0')}; transition: width 250ms ease-in-out; border-right: 1px solid ${(props) => props.theme.styles['border-color-base']}; - background-color: #f8f9fa; + background-color: ${ANTD_GRAY_V2[1]}; background: white; `; diff --git a/datahub-web-react/src/app/search/sidebar/ExpandableNode.tsx b/datahub-web-react/src/app/search/sidebar/ExpandableNode.tsx index 32d2c4af948eff..ba93cf94fba2be 100644 --- a/datahub-web-react/src/app/search/sidebar/ExpandableNode.tsx +++ b/datahub-web-react/src/app/search/sidebar/ExpandableNode.tsx @@ -1,9 +1,10 @@ import React, { MouseEventHandler, ReactNode } from 'react'; import styled from 'styled-components'; import { VscTriangleRight } from 'react-icons/vsc'; -import { Button, Typography } from 'antd'; +import { Typography } from 'antd'; import { UpCircleOutlined } from '@ant-design/icons'; import { ANTD_GRAY } from '../../entity/shared/constants'; +import { BaseButton, BodyContainer, BodyGridExpander, RotatingButton } from '../../shared/components'; const Layout = styled.div` margin-left: 8px; @@ -11,17 +12,6 @@ const Layout = styled.div` const HeaderContainer = styled.div``; -const BodyGridExpander = styled.div<{ isOpen: boolean }>` - display: grid; - grid-template-rows: ${(props) => (props.isOpen ? '1fr' : '0fr')}; - transition: grid-template-rows 250ms; - overflow: hidden; -`; - -const BodyContainer = styled.div` - min-height: 0; -`; - type ExpandableNodeProps = { isOpen: boolean; header: ReactNode; @@ -68,22 +58,6 @@ ExpandableNode.HeaderLeft = styled.div` align-items: center; `; -const BaseButton = styled(Button)` - &&& { - display: flex; - align-items: center; - justify-content: center; - border: none; - box-shadow: none; - border-radius: 50%; - } -`; - -const RotatingButton = styled(BaseButton)<{ deg: number }>` - transform: rotate(${(props) => props.deg}deg); - transition: transform 250ms; -`; - ExpandableNode.StaticButton = ({ icon, onClick }: { icon: JSX.Element; onClick?: () => void }) => { const onClickButton: MouseEventHandler = (e) => { e.stopPropagation(); diff --git a/datahub-web-react/src/app/search/suggestions/SearchQuerySugggester.tsx b/datahub-web-react/src/app/search/suggestions/SearchQuerySugggester.tsx new file mode 100644 index 00000000000000..9dbd67883bf642 --- /dev/null +++ b/datahub-web-react/src/app/search/suggestions/SearchQuerySugggester.tsx @@ -0,0 +1,39 @@ +import styled from 'styled-components'; +import React from 'react'; +import { useHistory } from 'react-router'; +import { SearchSuggestion } from '../../../types.generated'; +import { navigateToSearchUrl } from '../utils/navigateToSearchUrl'; +import { ANTD_GRAY_V2 } from '../../entity/shared/constants'; + +const TextWrapper = styled.div` + font-size: 14px; + color: ${ANTD_GRAY_V2[8]}; + margin: 16px 0 -8px 32px; +`; + +export const SuggestedText = styled.span` + color: ${(props) => props.theme.styles['primary-color']}; + text-decoration: underline ${(props) => props.theme.styles['primary-color']}; + cursor: pointer; +`; + +interface Props { + suggestions: SearchSuggestion[]; +} + +export default function SearchQuerySuggester({ suggestions }: Props) { + const history = useHistory(); + + if (suggestions.length === 0) return null; + const suggestText = suggestions[0].text; + + function searchForSuggestion() { + navigateToSearchUrl({ query: suggestText, history }); + } + + return ( + + Did you mean {suggestText} + + ); +} diff --git a/datahub-web-react/src/app/settings/SettingsPage.tsx b/datahub-web-react/src/app/settings/SettingsPage.tsx index bfec9b395cff21..339cc0cf44bace 100644 --- a/datahub-web-react/src/app/settings/SettingsPage.tsx +++ b/datahub-web-react/src/app/settings/SettingsPage.tsx @@ -7,6 +7,7 @@ import { ToolOutlined, FilterOutlined, TeamOutlined, + PushpinOutlined, } from '@ant-design/icons'; import { Redirect, Route, useHistory, useLocation, useRouteMatch, Switch } from 'react-router'; import styled from 'styled-components'; @@ -19,6 +20,7 @@ import { Preferences } from './Preferences'; import { ManageViews } from '../entity/view/ManageViews'; import { useUserContext } from '../context/useUserContext'; import { ManageOwnership } from '../entity/ownership/ManageOwnership'; +import ManagePosts from './posts/ManagePosts'; const PageContainer = styled.div` display: flex; @@ -62,6 +64,7 @@ const PATHS = [ { path: 'preferences', content: }, { path: 'views', content: }, { path: 'ownership', content: }, + { path: 'posts', content: }, ]; /** @@ -91,6 +94,7 @@ export const SettingsPage = () => { const showUsersGroups = (isIdentityManagementEnabled && me && me?.platformPrivileges?.manageIdentities) || false; const showViews = isViewsEnabled || false; const showOwnershipTypes = me && me?.platformPrivileges?.manageOwnershipTypes; + const showHomePagePosts = me && me?.platformPrivileges?.manageGlobalAnnouncements; return ( @@ -143,6 +147,11 @@ export const SettingsPage = () => { Ownership Types )} + {showHomePagePosts && ( + + Home Page Posts + + )} diff --git a/datahub-web-react/src/app/settings/posts/CreatePostForm.tsx b/datahub-web-react/src/app/settings/posts/CreatePostForm.tsx new file mode 100644 index 00000000000000..a8d6cfa64c9c14 --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/CreatePostForm.tsx @@ -0,0 +1,91 @@ +import React, { useState } from 'react'; +import { Form, Input, Typography, FormInstance, Radio } from 'antd'; +import styled from 'styled-components'; +import { + DESCRIPTION_FIELD_NAME, + LINK_FIELD_NAME, + LOCATION_FIELD_NAME, + TITLE_FIELD_NAME, + TYPE_FIELD_NAME, +} from './constants'; +import { PostContentType } from '../../../types.generated'; + +const TopFormItem = styled(Form.Item)` + margin-bottom: 24px; +`; + +const SubFormItem = styled(Form.Item)` + margin-bottom: 0; +`; + +type Props = { + setCreateButtonEnabled: (isEnabled: boolean) => void; + form: FormInstance; +}; + +export default function CreatePostForm({ setCreateButtonEnabled, form }: Props) { + const [postType, setPostType] = useState(PostContentType.Text); + + return ( +
{ + setCreateButtonEnabled(!form.getFieldsError().some((field) => field.errors.length > 0)); + }} + > + Post Type}> + setPostType(e.target.value)} + value={postType} + defaultValue={postType} + optionType="button" + buttonStyle="solid" + > + Announcement + Link + + + + Title}> + The title for your new post. + + + + + {postType === PostContentType.Text && ( + Description}> + The main content for your new post. + + + + + )} + {postType === PostContentType.Link && ( + <> + Link URL}> + + Where users will be directed when they click this post. + + + + + + Image URL}> + + A URL to an image you want to display on your link post. + + + + + + + )} +
+ ); +} diff --git a/datahub-web-react/src/app/settings/posts/CreatePostModal.tsx b/datahub-web-react/src/app/settings/posts/CreatePostModal.tsx new file mode 100644 index 00000000000000..b4851ecb029693 --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/CreatePostModal.tsx @@ -0,0 +1,107 @@ +import React, { useState } from 'react'; +import { Button, Form, message, Modal } from 'antd'; +import CreatePostForm from './CreatePostForm'; +import { + CREATE_POST_BUTTON_ID, + DESCRIPTION_FIELD_NAME, + LINK_FIELD_NAME, + LOCATION_FIELD_NAME, + TYPE_FIELD_NAME, + TITLE_FIELD_NAME, +} from './constants'; +import { useEnterKeyListener } from '../../shared/useEnterKeyListener'; +import { MediaType, PostContentType, PostType } from '../../../types.generated'; +import { useCreatePostMutation } from '../../../graphql/mutations.generated'; + +type Props = { + onClose: () => void; + onCreate: ( + contentType: string, + title: string, + description: string | undefined, + link: string | undefined, + location: string | undefined, + ) => void; +}; + +export default function CreatePostModal({ onClose, onCreate }: Props) { + const [createPostMutation] = useCreatePostMutation(); + const [createButtonEnabled, setCreateButtonEnabled] = useState(false); + const [form] = Form.useForm(); + const onCreatePost = () => { + const contentTypeValue = form.getFieldValue(TYPE_FIELD_NAME) ?? PostContentType.Text; + const mediaValue = + form.getFieldValue(TYPE_FIELD_NAME) && form.getFieldValue(LOCATION_FIELD_NAME) + ? { + type: MediaType.Image, + location: form.getFieldValue(LOCATION_FIELD_NAME) ?? null, + } + : null; + createPostMutation({ + variables: { + input: { + postType: PostType.HomePageAnnouncement, + content: { + contentType: contentTypeValue, + title: form.getFieldValue(TITLE_FIELD_NAME), + description: form.getFieldValue(DESCRIPTION_FIELD_NAME) ?? null, + link: form.getFieldValue(LINK_FIELD_NAME) ?? null, + media: mediaValue, + }, + }, + }, + }) + .then(({ errors }) => { + if (!errors) { + message.success({ + content: `Created Post!`, + duration: 3, + }); + onCreate( + form.getFieldValue(TYPE_FIELD_NAME) ?? PostContentType.Text, + form.getFieldValue(TITLE_FIELD_NAME), + form.getFieldValue(DESCRIPTION_FIELD_NAME), + form.getFieldValue(LINK_FIELD_NAME), + form.getFieldValue(LOCATION_FIELD_NAME), + ); + form.resetFields(); + } + }) + .catch((e) => { + message.destroy(); + message.error({ content: 'Failed to create Post! An unknown error occured.', duration: 3 }); + console.error('Failed to create Post:', e.message); + }); + onClose(); + }; + + // Handle the Enter press + useEnterKeyListener({ + querySelectorToExecuteClick: '#createPostButton', + }); + + return ( + + + + + } + > + + + ); +} diff --git a/datahub-web-react/src/app/settings/posts/ManagePosts.tsx b/datahub-web-react/src/app/settings/posts/ManagePosts.tsx new file mode 100644 index 00000000000000..e0f694c192c629 --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/ManagePosts.tsx @@ -0,0 +1,40 @@ +import { Typography } from 'antd'; +import React from 'react'; +import styled from 'styled-components/macro'; +import { PostList } from './PostsList'; + +const PageContainer = styled.div` + padding-top: 20px; + width: 100%; + height: 100%; +`; + +const PageHeaderContainer = styled.div` + && { + padding-left: 24px; + } +`; + +const PageTitle = styled(Typography.Title)` + && { + margin-bottom: 12px; + } +`; + +const ListContainer = styled.div``; + +export default function ManagePosts() { + return ( + + + Home Page Posts + + View and manage pinned posts that appear to all users on the landing page. + + + + + + + ); +} diff --git a/datahub-web-react/src/app/settings/posts/PostItemMenu.tsx b/datahub-web-react/src/app/settings/posts/PostItemMenu.tsx new file mode 100644 index 00000000000000..e3fc424a47ef28 --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/PostItemMenu.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { DeleteOutlined } from '@ant-design/icons'; +import { Dropdown, Menu, message, Modal } from 'antd'; +import { MenuIcon } from '../../entity/shared/EntityDropdown/EntityDropdown'; +import { useDeletePostMutation } from '../../../graphql/post.generated'; + +type Props = { + urn: string; + title: string; + onDelete?: () => void; +}; + +export default function PostItemMenu({ title, urn, onDelete }: Props) { + const [deletePostMutation] = useDeletePostMutation(); + + const deletePost = () => { + deletePostMutation({ + variables: { + urn, + }, + }) + .then(({ errors }) => { + if (!errors) { + message.success('Deleted Post!'); + onDelete?.(); + } + }) + .catch(() => { + message.destroy(); + message.error({ content: `Failed to delete Post!: An unknown error occurred.`, duration: 3 }); + }); + }; + + const onConfirmDelete = () => { + Modal.confirm({ + title: `Delete Post '${title}'`, + content: `Are you sure you want to remove this Post?`, + onOk() { + deletePost(); + }, + onCancel() {}, + okText: 'Yes', + maskClosable: true, + closable: true, + }); + }; + + return ( + + +  Delete + + + } + > + + + ); +} diff --git a/datahub-web-react/src/app/settings/posts/PostsList.tsx b/datahub-web-react/src/app/settings/posts/PostsList.tsx new file mode 100644 index 00000000000000..5ae2be1547f9b7 --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/PostsList.tsx @@ -0,0 +1,200 @@ +import React, { useEffect, useState } from 'react'; +import { Button, Empty, Pagination, Typography } from 'antd'; +import { useLocation } from 'react-router'; +import styled from 'styled-components'; +import * as QueryString from 'query-string'; +import { PlusOutlined } from '@ant-design/icons'; +import { AlignType } from 'rc-table/lib/interface'; +import CreatePostModal from './CreatePostModal'; +import { PostColumn, PostEntry, PostListMenuColumn } from './PostsListColumns'; +import { useEntityRegistry } from '../../useEntityRegistry'; +import { useListPostsQuery } from '../../../graphql/post.generated'; +import { scrollToTop } from '../../shared/searchUtils'; +import { addToListPostCache, removeFromListPostCache } from './utils'; +import { Message } from '../../shared/Message'; +import TabToolbar from '../../entity/shared/components/styled/TabToolbar'; +import { SearchBar } from '../../search/SearchBar'; +import { StyledTable } from '../../entity/shared/components/styled/StyledTable'; +import { POST_TYPE_TO_DISPLAY_TEXT } from './constants'; + +const PostsContainer = styled.div``; + +export const PostsPaginationContainer = styled.div` + display: flex; + justify-content: center; + padding: 12px; + padding-left: 16px; + border-bottom: 1px solid; + border-color: ${(props) => props.theme.styles['border-color-base']}; + display: flex; + justify-content: space-between; + align-items: center; +`; + +const PaginationInfo = styled(Typography.Text)` + padding: 0px; +`; + +const DEFAULT_PAGE_SIZE = 10; + +export const PostList = () => { + const entityRegistry = useEntityRegistry(); + const location = useLocation(); + const params = QueryString.parse(location.search, { arrayFormat: 'comma' }); + const paramsQuery = (params?.query as string) || undefined; + const [query, setQuery] = useState(undefined); + useEffect(() => setQuery(paramsQuery), [paramsQuery]); + + const [page, setPage] = useState(1); + const [isCreatingPost, setIsCreatingPost] = useState(false); + + const pageSize = DEFAULT_PAGE_SIZE; + const start = (page - 1) * pageSize; + + const { loading, error, data, client, refetch } = useListPostsQuery({ + variables: { + input: { + start, + count: pageSize, + query, + }, + }, + fetchPolicy: query && query.length > 0 ? 'no-cache' : 'cache-first', + }); + + const totalPosts = data?.listPosts?.total || 0; + const lastResultIndex = start + pageSize > totalPosts ? totalPosts : start + pageSize; + const posts = data?.listPosts?.posts || []; + + const onChangePage = (newPage: number) => { + scrollToTop(); + setPage(newPage); + }; + + const handleDelete = (urn: string) => { + removeFromListPostCache(client, urn, page, pageSize); + setTimeout(() => { + refetch?.(); + }, 2000); + }; + + const allColumns = [ + { + title: 'Title', + dataIndex: '', + key: 'title', + sorter: (sourceA, sourceB) => { + return sourceA.title.localeCompare(sourceB.title); + }, + render: (record: PostEntry) => PostColumn(record.title, 200), + width: '20%', + }, + { + title: 'Description', + dataIndex: '', + key: 'description', + render: (record: PostEntry) => PostColumn(record.description || ''), + }, + { + title: 'Type', + dataIndex: '', + key: 'type', + render: (record: PostEntry) => PostColumn(POST_TYPE_TO_DISPLAY_TEXT[record.contentType]), + style: { minWidth: 100 }, + width: '10%', + }, + { + title: '', + dataIndex: '', + width: '5%', + align: 'right' as AlignType, + key: 'menu', + render: PostListMenuColumn(handleDelete), + }, + ]; + + const tableData = posts.map((post) => { + return { + urn: post.urn, + title: post.content.title, + description: post.content.description, + contentType: post.content.contentType, + }; + }); + + return ( + <> + {!data && loading && } + {error && } + + + + null} + onQueryChange={(q) => setQuery(q && q.length > 0 ? q : undefined)} + entityRegistry={entityRegistry} + hideRecommendations + /> + + }} + /> + {totalPosts > pageSize && ( + + + + {lastResultIndex > 0 ? (page - 1) * pageSize + 1 : 0} - {lastResultIndex} + {' '} + of {totalPosts} + + + + + )} + {isCreatingPost && ( + setIsCreatingPost(false)} + onCreate={(urn, title, description) => { + addToListPostCache( + client, + { + urn, + properties: { + title, + description: description || null, + }, + }, + pageSize, + ); + setTimeout(() => refetch(), 2000); + }} + /> + )} + + + ); +}; diff --git a/datahub-web-react/src/app/settings/posts/PostsListColumns.tsx b/datahub-web-react/src/app/settings/posts/PostsListColumns.tsx new file mode 100644 index 00000000000000..38f910baf8f412 --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/PostsListColumns.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +// import { Typography } from 'antd'; +import styled from 'styled-components/macro'; +import { Maybe } from 'graphql/jsutils/Maybe'; +import PostItemMenu from './PostItemMenu'; + +export interface PostEntry { + title: string; + contentType: string; + description: Maybe; + urn: string; +} + +const PostText = styled.div<{ minWidth?: number }>` + ${(props) => props.minWidth !== undefined && `min-width: ${props.minWidth}px;`} +`; + +export function PostListMenuColumn(handleDelete: (urn: string) => void) { + return (record: PostEntry) => ( + handleDelete(record.urn)} /> + ); +} + +export function PostColumn(text: string, minWidth?: number) { + return {text}; +} diff --git a/datahub-web-react/src/app/settings/posts/constants.ts b/datahub-web-react/src/app/settings/posts/constants.ts new file mode 100644 index 00000000000000..5a164019fe2e55 --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/constants.ts @@ -0,0 +1,13 @@ +import { PostContentType } from '../../../types.generated'; + +export const TITLE_FIELD_NAME = 'title'; +export const DESCRIPTION_FIELD_NAME = 'description'; +export const LINK_FIELD_NAME = 'link'; +export const LOCATION_FIELD_NAME = 'location'; +export const TYPE_FIELD_NAME = 'type'; +export const CREATE_POST_BUTTON_ID = 'createPostButton'; + +export const POST_TYPE_TO_DISPLAY_TEXT = { + [PostContentType.Link]: 'Link', + [PostContentType.Text]: 'Announcement', +}; diff --git a/datahub-web-react/src/app/settings/posts/utils.ts b/datahub-web-react/src/app/settings/posts/utils.ts new file mode 100644 index 00000000000000..ce48c7400738ce --- /dev/null +++ b/datahub-web-react/src/app/settings/posts/utils.ts @@ -0,0 +1,77 @@ +import { ListPostsDocument, ListPostsQuery } from '../../../graphql/post.generated'; + +/** + * Add an entry to the list posts cache. + */ +export const addToListPostCache = (client, newPost, pageSize) => { + // Read the data from our cache for this query. + const currData: ListPostsQuery | null = client.readQuery({ + query: ListPostsDocument, + variables: { + input: { + start: 0, + count: pageSize, + }, + }, + }); + + // Add our new post into the existing list. + const newPosts = [newPost, ...(currData?.listPosts?.posts || [])]; + + // Write our data back to the cache. + client.writeQuery({ + query: ListPostsDocument, + variables: { + input: { + start: 0, + count: pageSize, + }, + }, + data: { + listPosts: { + start: 0, + count: (currData?.listPosts?.count || 0) + 1, + total: (currData?.listPosts?.total || 0) + 1, + posts: newPosts, + }, + }, + }); +}; + +/** + * Remove an entry from the list posts cache. + */ +export const removeFromListPostCache = (client, urn, page, pageSize) => { + // Read the data from our cache for this query. + const currData: ListPostsQuery | null = client.readQuery({ + query: ListPostsDocument, + variables: { + input: { + start: (page - 1) * pageSize, + count: pageSize, + }, + }, + }); + + // Remove the post from the existing posts set. + const newPosts = [...(currData?.listPosts?.posts || []).filter((post) => post.urn !== urn)]; + + // Write our data back to the cache. + client.writeQuery({ + query: ListPostsDocument, + variables: { + input: { + start: (page - 1) * pageSize, + count: pageSize, + }, + }, + data: { + listPosts: { + start: currData?.listPosts?.start || 0, + count: (currData?.listPosts?.count || 1) - 1, + total: (currData?.listPosts?.total || 1) - 1, + posts: newPosts, + }, + }, + }); +}; diff --git a/datahub-web-react/src/app/shared/LogoCountCard.tsx b/datahub-web-react/src/app/shared/LogoCountCard.tsx index 3e2f74ebe5166c..ebf0d9cd4f54ee 100644 --- a/datahub-web-react/src/app/shared/LogoCountCard.tsx +++ b/datahub-web-react/src/app/shared/LogoCountCard.tsx @@ -1,27 +1,9 @@ import React from 'react'; -import { Image, Typography, Button } from 'antd'; +import { Image, Typography } from 'antd'; import styled from 'styled-components'; import { ANTD_GRAY } from '../entity/shared/constants'; import { formatNumber } from './formatNumber'; - -const Container = styled(Button)` - margin-right: 12px; - margin-left: 12px; - margin-bottom: 12px; - width: 160px; - height: 140px; - display: flex; - justify-content: center; - border-radius: 4px; - align-items: center; - flex-direction: column; - border: 1px solid ${ANTD_GRAY[4]}; - box-shadow: ${(props) => props.theme.styles['box-shadow']}; - &&:hover { - box-shadow: ${(props) => props.theme.styles['box-shadow-hover']}; - } - white-space: unset; -`; +import { HomePageButton } from './components'; const PlatformLogo = styled(Image)` max-height: 32px; @@ -53,7 +35,7 @@ type Props = { export const LogoCountCard = ({ logoUrl, logoComponent, name, count, onClick }: Props) => { return ( - + {(logoUrl && ) || logoComponent} @@ -68,6 +50,6 @@ export const LogoCountCard = ({ logoUrl, logoComponent, name, count, onClick }: {count !== undefined && {formatNumber(count)}} - + ); }; diff --git a/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx b/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx index 39035d5bff562f..ced7d8642576b3 100644 --- a/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx +++ b/datahub-web-react/src/app/shared/admin/HeaderLinks.tsx @@ -5,7 +5,6 @@ import { BarChartOutlined, BookOutlined, SettingOutlined, - FolderOutlined, SolutionOutlined, DownOutlined, } from '@ant-design/icons'; @@ -16,6 +15,7 @@ import { ANTD_GRAY } from '../../entity/shared/constants'; import { HOME_PAGE_INGESTION_ID } from '../../onboarding/config/HomePageOnboardingConfig'; import { useUpdateEducationStepIdsAllowlist } from '../../onboarding/useUpdateEducationStepIdsAllowlist'; import { useUserContext } from '../../context/useUserContext'; +import DomainIcon from '../../domain/DomainIcon'; const LinkWrapper = styled.span` margin-right: 0px; @@ -124,7 +124,12 @@ export function HeaderLinks(props: Props) { - + Domains Manage related groups of data assets diff --git a/datahub-web-react/src/app/shared/components.tsx b/datahub-web-react/src/app/shared/components.tsx new file mode 100644 index 00000000000000..68d2fb52cfdba0 --- /dev/null +++ b/datahub-web-react/src/app/shared/components.tsx @@ -0,0 +1,49 @@ +import { Button } from 'antd'; +import styled from 'styled-components'; +import { ANTD_GRAY } from '../entity/shared/constants'; + +export const HomePageButton = styled(Button)` + margin-right: 12px; + margin-left: 12px; + margin-bottom: 12px; + width: 160px; + height: 140px; + display: flex; + justify-content: center; + border-radius: 4px; + align-items: center; + flex-direction: column; + border: 1px solid ${ANTD_GRAY[4]}; + box-shadow: ${(props) => props.theme.styles['box-shadow']}; + &&:hover { + box-shadow: ${(props) => props.theme.styles['box-shadow-hover']}; + } + white-space: unset; +`; + +export const BaseButton = styled(Button)` + &&& { + display: flex; + align-items: center; + justify-content: center; + border: none; + box-shadow: none; + border-radius: 50%; + } +`; + +export const RotatingButton = styled(BaseButton)<{ deg: number }>` + transform: rotate(${(props) => props.deg}deg); + transition: transform 250ms; +`; + +export const BodyGridExpander = styled.div<{ isOpen: boolean }>` + display: grid; + grid-template-rows: ${(props) => (props.isOpen ? '1fr' : '0fr')}; + transition: grid-template-rows 250ms; + overflow: hidden; +`; + +export const BodyContainer = styled.div` + min-height: 0; +`; diff --git a/datahub-web-react/src/app/shared/deleteUtils.ts b/datahub-web-react/src/app/shared/deleteUtils.ts index c1bfeac37372bc..37a3758712ad6c 100644 --- a/datahub-web-react/src/app/shared/deleteUtils.ts +++ b/datahub-web-react/src/app/shared/deleteUtils.ts @@ -1,3 +1,4 @@ +import { PageRoutes } from '../../conf/Global'; import { useDeleteAssertionMutation } from '../../graphql/assertion.generated'; import { useDeleteDataProductMutation } from '../../graphql/dataProduct.generated'; import { useDeleteDomainMutation } from '../../graphql/domain.generated'; @@ -18,10 +19,11 @@ export const getEntityProfileDeleteRedirectPath = (type: EntityType, entityData: switch (type) { case EntityType.CorpGroup: case EntityType.CorpUser: - case EntityType.Domain: case EntityType.Tag: // Return Home. return '/'; + case EntityType.Domain: + return `${PageRoutes.DOMAINS}`; case EntityType.GlossaryNode: case EntityType.GlossaryTerm: // Return to glossary page. diff --git a/datahub-web-react/src/app/shared/health/healthUtils.tsx b/datahub-web-react/src/app/shared/health/healthUtils.tsx index 823d77d7eabe9e..ff7d9b417617cc 100644 --- a/datahub-web-react/src/app/shared/health/healthUtils.tsx +++ b/datahub-web-react/src/app/shared/health/healthUtils.tsx @@ -11,13 +11,17 @@ import { HealthStatus, HealthStatusType, Health } from '../../../types.generated const HEALTH_INDICATOR_COLOR = '#d48806'; -const UnhealthyIconFilled = styled(ExclamationCircleTwoTone)` - font-size: 16px; +const UnhealthyIconFilled = styled(ExclamationCircleTwoTone)<{ fontSize: number }>` + && { + font-size: ${(props) => props.fontSize}px; + } `; -const UnhealthyIconOutlined = styled(ExclamationCircleOutlined)` +const UnhealthyIconOutlined = styled(ExclamationCircleOutlined)<{ fontSize: number }>` color: ${HEALTH_INDICATOR_COLOR}; - font-size: 16px; + && { + font-size: ${(props) => props.fontSize}px; + } `; export enum HealthSummaryIconType { @@ -32,12 +36,16 @@ export const isUnhealthy = (healths: Health[]) => { return isFailingAssertions; }; -export const getHealthSummaryIcon = (healths: Health[], type: HealthSummaryIconType = HealthSummaryIconType.FILLED) => { +export const getHealthSummaryIcon = ( + healths: Health[], + type: HealthSummaryIconType = HealthSummaryIconType.FILLED, + fontSize = 16, +) => { const unhealthy = isUnhealthy(healths); return unhealthy - ? (type === HealthSummaryIconType.FILLED && ) || ( - - ) + ? (type === HealthSummaryIconType.FILLED && ( + + )) || : undefined; }; diff --git a/datahub-web-react/src/app/shared/sidebar/components.tsx b/datahub-web-react/src/app/shared/sidebar/components.tsx new file mode 100644 index 00000000000000..5d123d60227906 --- /dev/null +++ b/datahub-web-react/src/app/shared/sidebar/components.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { RightOutlined } from '@ant-design/icons'; +import styled from 'styled-components'; +import { RotatingButton } from '../components'; + +export const SidebarWrapper = styled.div<{ width: number }>` + max-height: 100%; + width: ${(props) => props.width}px; + min-width: ${(props) => props.width}px; +`; + +export function RotatingTriangle({ isOpen, onClick }: { isOpen: boolean; onClick?: () => void }) { + return ( + } + onClick={onClick} + /> + ); +} diff --git a/datahub-web-react/src/app/shared/styleUtils.ts b/datahub-web-react/src/app/shared/styleUtils.ts new file mode 100644 index 00000000000000..21bc866218cb87 --- /dev/null +++ b/datahub-web-react/src/app/shared/styleUtils.ts @@ -0,0 +1,7 @@ +export function applyOpacity(hexColor: string, opacity: number) { + if (hexColor.length !== 7) return hexColor; + + const updatedOpacity = Math.round(opacity * 2.55); + + return hexColor + updatedOpacity.toString(16).padStart(2, '0'); +} diff --git a/datahub-web-react/src/app/shared/tags/AddTagsTermsModal.tsx b/datahub-web-react/src/app/shared/tags/AddTagsTermsModal.tsx index 01e11ceb9a7387..80d239def391c0 100644 --- a/datahub-web-react/src/app/shared/tags/AddTagsTermsModal.tsx +++ b/datahub-web-react/src/app/shared/tags/AddTagsTermsModal.tsx @@ -50,15 +50,15 @@ const StyleTag = styled(CustomTag)` line-height: 16px; `; -export const BrowserWrapper = styled.div<{ isHidden: boolean }>` +export const BrowserWrapper = styled.div<{ isHidden: boolean; width?: string; maxHeight?: number }>` background-color: white; border-radius: 5px; box-shadow: 0 3px 6px -4px rgb(0 0 0 / 12%), 0 6px 16px 0 rgb(0 0 0 / 8%), 0 9px 28px 8px rgb(0 0 0 / 5%); - max-height: 380px; + max-height: ${(props) => (props.maxHeight ? props.maxHeight : '380')}px; overflow: auto; position: absolute; transition: opacity 0.2s; - width: 480px; + width: ${(props) => (props.width ? props.width : '480px')}; z-index: 1051; ${(props) => props.isHidden && diff --git a/datahub-web-react/src/app/shared/tags/DomainLink.tsx b/datahub-web-react/src/app/shared/tags/DomainLink.tsx index 1c14b71369ed61..a14114ce43e438 100644 --- a/datahub-web-react/src/app/shared/tags/DomainLink.tsx +++ b/datahub-web-react/src/app/shared/tags/DomainLink.tsx @@ -3,10 +3,10 @@ import React from 'react'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { Domain, EntityType } from '../../../types.generated'; -import { IconStyleType } from '../../entity/Entity'; import { HoverEntityTooltip } from '../../recommendations/renderer/component/HoverEntityTooltip'; import { useEntityRegistry } from '../../useEntityRegistry'; import { ANTD_GRAY } from '../../entity/shared/constants'; +import DomainIcon from '../../domain/DomainIcon'; const DomainLinkContainer = styled(Link)` display: inline-block; @@ -39,7 +39,12 @@ function DomainContent({ domain, name, closable, onClose, tagStyle, fontSize }: return ( - {entityRegistry.getIcon(EntityType.Domain, fontSize || 10, IconStyleType.ACCENT, ANTD_GRAY[9])} + {displayName} diff --git a/datahub-web-react/src/app/shared/tags/tag/Tag.tsx b/datahub-web-react/src/app/shared/tags/tag/Tag.tsx index 2288238091776b..ed2460b6eea3ce 100644 --- a/datahub-web-react/src/app/shared/tags/tag/Tag.tsx +++ b/datahub-web-react/src/app/shared/tags/tag/Tag.tsx @@ -8,6 +8,7 @@ import { StyledTag } from '../../../entity/shared/components/styled/StyledTag'; import { HoverEntityTooltip } from '../../../recommendations/renderer/component/HoverEntityTooltip'; import { useEntityRegistry } from '../../../useEntityRegistry'; import { TagProfileDrawer } from '../TagProfileDrawer'; +import { useHasMatchedFieldByUrn } from '../../../search/context/SearchResultContext'; const TagLink = styled.span` display: inline-block; @@ -41,6 +42,7 @@ export default function Tag({ }: Props) { const entityRegistry = useEntityRegistry(); const [removeTagMutation] = useRemoveTagMutation(); + const highlightTag = useHasMatchedFieldByUrn(tag.tag.urn, 'tags'); const [tagProfileDrawerVisible, setTagProfileDrawerVisible] = useState(false); const [addTagUrn, setAddTagUrn] = useState(''); @@ -110,6 +112,7 @@ export default function Tag({ removeTag(tag); }} fontSize={fontSize} + highlightTag={highlightTag} > ` +const StyledTag = styled(Tag)<{ fontSize?: number; highlightTerm?: boolean }>` + &&& { + ${(props) => + props.highlightTerm && + ` + background: ${props.theme.styles['highlight-color']}; + border: 1px solid ${props.theme.styles['highlight-border-color']}; + `} + } ${(props) => props.fontSize && `font-size: ${props.fontSize}px;`} `; @@ -38,6 +47,7 @@ export default function TermContent({ }: Props) { const entityRegistry = useEntityRegistry(); const [removeTermMutation] = useRemoveTermMutation(); + const highlightTerm = useHasMatchedFieldByUrn(term.term.urn, 'glossaryTerms'); const removeTerm = (termToRemove: GlossaryTermAssociation) => { onOpenModal?.(); @@ -85,6 +95,7 @@ export default function TermContent({ removeTerm(term); }} fontSize={fontSize} + highlightTerm={highlightTerm} > diff --git a/datahub-web-react/src/app/shared/useToggle.ts b/datahub-web-react/src/app/shared/useToggle.ts index b020bf030f079f..a73c702c4351bf 100644 --- a/datahub-web-react/src/app/shared/useToggle.ts +++ b/datahub-web-react/src/app/shared/useToggle.ts @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useMemo, useState } from 'react'; const NOOP = (_: boolean) => {}; @@ -9,25 +9,39 @@ const useToggle = ({ initialValue = false, closeDelay = 0, openDelay = 0, onTogg const isClosing = transition === 'closing'; const isTransitioning = transition !== null; - const toggle = () => { - if (isOpen) { + const toggleClose = useMemo( + () => () => { setTransition('closing'); window.setTimeout(() => { setIsOpen(false); setTransition(null); onToggle(false); }, closeDelay); - } else { + }, + [closeDelay, onToggle], + ); + + const toggleOpen = useMemo( + () => () => { setTransition('opening'); window.setTimeout(() => { setIsOpen(true); setTransition(null); onToggle(true); }, openDelay); + }, + [openDelay, onToggle], + ); + + const toggle = () => { + if (isOpen) { + toggleClose(); + } else { + toggleOpen(); } }; - return { isOpen, isClosing, isOpening, isTransitioning, toggle } as const; + return { isOpen, isClosing, isOpening, isTransitioning, toggle, toggleOpen, toggleClose } as const; }; export default useToggle; diff --git a/datahub-web-react/src/app/useAppConfig.ts b/datahub-web-react/src/app/useAppConfig.ts index cdc8f92210a0dc..821d00b9017c31 100644 --- a/datahub-web-react/src/app/useAppConfig.ts +++ b/datahub-web-react/src/app/useAppConfig.ts @@ -12,3 +12,8 @@ export function useIsShowAcrylInfoEnabled() { const appConfig = useAppConfig(); return appConfig.config.featureFlags.showAcrylInfo; } + +export function useIsNestedDomainsEnabled() { + const appConfig = useAppConfig(); + return appConfig.config.featureFlags.nestedDomainsEnabled; +} diff --git a/datahub-web-react/src/appConfigContext.tsx b/datahub-web-react/src/appConfigContext.tsx index 3b34b108ecc93d..4087ad453687c8 100644 --- a/datahub-web-react/src/appConfigContext.tsx +++ b/datahub-web-react/src/appConfigContext.tsx @@ -27,6 +27,9 @@ export const DEFAULT_APP_CONFIG = { entityProfile: { domainDefaultTab: null, }, + searchResult: { + enableNameHighlight: false, + }, }, authConfig: { tokenAuthEnabled: false, @@ -45,6 +48,8 @@ export const DEFAULT_APP_CONFIG = { showSearchFiltersV2: true, showBrowseV2: true, showAcrylInfo: false, + showAccessManagement: false, + nestedDomainsEnabled: true, }, }; diff --git a/datahub-web-react/src/conf/Global.ts b/datahub-web-react/src/conf/Global.ts index b16dd1eaace57b..82378bb6214271 100644 --- a/datahub-web-react/src/conf/Global.ts +++ b/datahub-web-react/src/conf/Global.ts @@ -24,10 +24,12 @@ export enum PageRoutes { INGESTION = '/ingestion', SETTINGS = '/settings', DOMAINS = '/domains', + DOMAIN = '/domain', GLOSSARY = '/glossary', SETTINGS_VIEWS = '/settings/views', EMBED = '/embed', EMBED_LOOKUP = '/embed/lookup/:url', + SETTINGS_POSTS = '/settings/posts', } /** diff --git a/datahub-web-react/src/conf/theme/theme_dark.config.json b/datahub-web-react/src/conf/theme/theme_dark.config.json index b648f3d997f217..9746c3ddde5f37 100644 --- a/datahub-web-react/src/conf/theme/theme_dark.config.json +++ b/datahub-web-react/src/conf/theme/theme_dark.config.json @@ -17,7 +17,9 @@ "disabled-color": "fade(white, 25%)", "steps-nav-arrow-color": "fade(white, 25%)", "homepage-background-upper-fade": "#FFFFFF", - "homepage-background-lower-fade": "#333E4C" + "homepage-background-lower-fade": "#333E4C", + "highlight-color": "#E6F4FF", + "highlight-border-color": "#BAE0FF" }, "assets": { "logoUrl": "/assets/logo.png" diff --git a/datahub-web-react/src/conf/theme/theme_light.config.json b/datahub-web-react/src/conf/theme/theme_light.config.json index e842fdb1bb8aad..906c04e38a1baf 100644 --- a/datahub-web-react/src/conf/theme/theme_light.config.json +++ b/datahub-web-react/src/conf/theme/theme_light.config.json @@ -20,7 +20,9 @@ "homepage-background-lower-fade": "#FFFFFF", "homepage-text-color": "#434343", "box-shadow": "0px 0px 30px 0px rgb(239 239 239)", - "box-shadow-hover": "0px 1px 0px 0.5px rgb(239 239 239)" + "box-shadow-hover": "0px 1px 0px 0.5px rgb(239 239 239)", + "highlight-color": "#E6F4FF", + "highlight-border-color": "#BAE0FF" }, "assets": { "logoUrl": "/assets/logo.png" diff --git a/datahub-web-react/src/conf/theme/types.ts b/datahub-web-react/src/conf/theme/types.ts index 98140cbbd553d9..7d78230092700a 100644 --- a/datahub-web-react/src/conf/theme/types.ts +++ b/datahub-web-react/src/conf/theme/types.ts @@ -18,6 +18,8 @@ export type Theme = { 'homepage-background-lower-fade': string; 'box-shadow': string; 'box-shadow-hover': string; + 'highlight-color': string; + 'highlight-border-color': string; }; assets: { logoUrl: string; diff --git a/datahub-web-react/src/graphql/accessrole.graphql b/datahub-web-react/src/graphql/accessrole.graphql new file mode 100644 index 00000000000000..ccc7d3496ad6df --- /dev/null +++ b/datahub-web-react/src/graphql/accessrole.graphql @@ -0,0 +1,8 @@ +query getExternalRole($urn: String!) { + role(urn: $urn) { + properties { + name + description + } + } +} \ No newline at end of file diff --git a/datahub-web-react/src/graphql/app.graphql b/datahub-web-react/src/graphql/app.graphql index 4b1295f1024a29..4e9bbb11d8c5aa 100644 --- a/datahub-web-react/src/graphql/app.graphql +++ b/datahub-web-react/src/graphql/app.graphql @@ -45,6 +45,9 @@ query appConfig { defaultTab } } + searchResult { + enableNameHighlight + } } telemetryConfig { enableThirdPartyLogging @@ -60,6 +63,8 @@ query appConfig { showSearchFiltersV2 showBrowseV2 showAcrylInfo + showAccessManagement + nestedDomainsEnabled } } } diff --git a/datahub-web-react/src/graphql/dataset.graphql b/datahub-web-react/src/graphql/dataset.graphql index c79c1a4d9d5514..658ce2b47c5676 100644 --- a/datahub-web-react/src/graphql/dataset.graphql +++ b/datahub-web-react/src/graphql/dataset.graphql @@ -311,3 +311,34 @@ query getDatasetSchema($urn: String!) { } } } + +query getExternalRoles($urn: String!) { + dataset(urn: $urn) { + access { + ...getRoles + } + __typename + } +} + +fragment getRoles on Access { + roles { + role { + id + properties { + name + description + type + requestUrl + } + urn + actors { + users { + user { + urn + } + } + } + } + } +} diff --git a/datahub-web-react/src/graphql/domain.graphql b/datahub-web-react/src/graphql/domain.graphql index d72ff336bf9e7e..951b93fcba9af1 100644 --- a/datahub-web-react/src/graphql/domain.graphql +++ b/datahub-web-react/src/graphql/domain.graphql @@ -2,10 +2,14 @@ query getDomain($urn: String!) { domain(urn: $urn) { urn id + type properties { name description } + parentDomains { + ...parentDomainsFields + } ownership { ...ownershipFields } @@ -23,6 +27,9 @@ query getDomain($urn: String!) { } } } + children: relationships(input: { types: ["IsPartOf"], direction: INCOMING, start: 0, count: 0 }) { + total + } } } @@ -33,16 +40,29 @@ query listDomains($input: ListDomainsInput!) { total domains { urn + id + type properties { name description } + parentDomains { + ...parentDomainsFields + } ownership { ...ownershipFields } - entities(input: { start: 0, count: 1 }) { - total - } + ...domainEntitiesFields + } + } +} + +query getDomainChildrenCount($urn: String!) { + domain(urn: $urn) { + urn + type + children: relationships(input: { types: ["IsPartOf"], direction: INCOMING, start: 0, count: 0 }) { + total } } } @@ -51,6 +71,10 @@ mutation createDomain($input: CreateDomainInput!) { createDomain(input: $input) } +mutation moveDomain($input: MoveDomainInput!) { + moveDomain(input: $input) +} + mutation deleteDomain($urn: String!) { deleteDomain(urn: $urn) } diff --git a/datahub-web-react/src/graphql/fragments.graphql b/datahub-web-react/src/graphql/fragments.graphql index c3ac2139e687be..72474911b93101 100644 --- a/datahub-web-react/src/graphql/fragments.graphql +++ b/datahub-web-react/src/graphql/fragments.graphql @@ -82,6 +82,20 @@ fragment parentNodesFields on ParentNodesResult { } } +fragment parentDomainsFields on ParentDomainsResult { + count + domains { + urn + type + ... on Domain { + properties { + name + description + } + } + } +} + fragment ownershipFields on Ownership { owners { owner { @@ -931,6 +945,20 @@ fragment parentContainerFields on Container { } } +fragment domainEntitiesFields on Domain { + entities(input: { start: 0, count: 0 }) { + total + } + dataProducts: entities( + input: { start: 0, count: 0, filters: [{ field: "_entityType", value: "DATA_PRODUCT" }] } + ) { + total + } + children: relationships(input: { types: ["IsPartOf"], direction: INCOMING, start: 0, count: 0 }) { + total + } +} + fragment entityDomain on DomainAssociation { domain { urn @@ -939,6 +967,10 @@ fragment entityDomain on DomainAssociation { name description } + parentDomains { + ...parentDomainsFields + } + ...domainEntitiesFields } associatedUrn } diff --git a/datahub-web-react/src/graphql/lineage.graphql b/datahub-web-react/src/graphql/lineage.graphql index 61c79abf929a02..52385dee8631ac 100644 --- a/datahub-web-react/src/graphql/lineage.graphql +++ b/datahub-web-react/src/graphql/lineage.graphql @@ -198,6 +198,12 @@ fragment lineageNodeProperties on EntityWithRelationships { path } } + health { + type + status + message + causes + } } ... on MLModelGroup { urn diff --git a/datahub-web-react/src/graphql/me.graphql b/datahub-web-react/src/graphql/me.graphql index 2c693c747af56c..af850c9c3ce286 100644 --- a/datahub-web-react/src/graphql/me.graphql +++ b/datahub-web-react/src/graphql/me.graphql @@ -46,6 +46,7 @@ query getMe { createTags manageGlobalViews manageOwnershipTypes + manageGlobalAnnouncements } } } diff --git a/datahub-web-react/src/graphql/post.graphql b/datahub-web-react/src/graphql/post.graphql index c19f38fc7751c1..ee092ad4fba90d 100644 --- a/datahub-web-react/src/graphql/post.graphql +++ b/datahub-web-react/src/graphql/post.graphql @@ -20,3 +20,11 @@ query listPosts($input: ListPostsInput!) { } } } + +mutation createPost($input: CreatePostInput!) { + createPost(input: $input) +} + +mutation deletePost($urn: String!) { + deletePost(urn: $urn) +} diff --git a/datahub-web-react/src/graphql/preview.graphql b/datahub-web-react/src/graphql/preview.graphql index 03635ab1b66d5b..e104d62c670741 100644 --- a/datahub-web-react/src/graphql/preview.graphql +++ b/datahub-web-react/src/graphql/preview.graphql @@ -304,7 +304,12 @@ fragment entityPreview on Entity { urn properties { name + description + } + parentDomains { + ...parentDomainsFields } + ...domainEntitiesFields } ... on Container { ...entityContainer diff --git a/datahub-web-react/src/graphql/search.graphql b/datahub-web-react/src/graphql/search.graphql index 172a6d957e2874..2297c2d0c1d075 100644 --- a/datahub-web-react/src/graphql/search.graphql +++ b/datahub-web-react/src/graphql/search.graphql @@ -44,6 +44,16 @@ fragment autoCompleteFields on Entity { } } ...datasetStatsFields + access { + ...getAccess + } + } + ... on Role { + id + properties { + name + description + } } ... on CorpUser { username @@ -145,6 +155,9 @@ fragment autoCompleteFields on Entity { properties { name } + parentDomains { + ...parentDomainsFields + } } ... on DataProduct { properties { @@ -242,6 +255,25 @@ query getAutoCompleteMultipleResults($input: AutoCompleteMultipleInput!) { } } +fragment getAccess on Access { + roles { + role { + ...getRolesName + } + } +} + +fragment getRolesName on Role { + urn + type + id + properties { + name + description + type + } +} + fragment datasetStatsFields on Dataset { lastProfile: datasetProfiles(limit: 1) { rowCount @@ -288,6 +320,9 @@ fragment nonSiblingsDatasetSearchFields on Dataset { editableProperties { description } + access { + ...getAccess + } platformNativeType properties { name @@ -346,6 +381,13 @@ fragment searchResultFields on Entity { } } } + ... on Role { + id + properties { + name + description + } + } ... on CorpUser { username properties { @@ -632,6 +674,10 @@ fragment searchResultFields on Entity { ownership { ...ownershipFields } + parentDomains { + ...parentDomainsFields + } + ...domainEntitiesFields } ... on Container { properties { @@ -786,6 +832,9 @@ fragment facetFields on FacetMetadata { properties { name } + parentDomains { + ...parentDomainsFields + } } ... on Container { platform { @@ -832,6 +881,11 @@ fragment searchResults on SearchResults { matchedFields { name value + entity { + urn + type + ...entityDisplayNameFields + } } insights { text @@ -841,6 +895,11 @@ fragment searchResults on SearchResults { facets { ...facetFields } + suggestions { + text + frequency + score + } } fragment schemaFieldEntityFields on SchemaFieldEntity { diff --git a/datahub-web-react/src/images/dynamodblogo.png b/datahub-web-react/src/images/dynamodblogo.png new file mode 100644 index 00000000000000..f5beafb035772c Binary files /dev/null and b/datahub-web-react/src/images/dynamodblogo.png differ diff --git a/datahub-web-react/yarn.lock b/datahub-web-react/yarn.lock index e5bb6ce33eebc5..590f3ebcef8c33 100644 --- a/datahub-web-react/yarn.lock +++ b/datahub-web-react/yarn.lock @@ -15,17 +15,28 @@ resolved "https://registry.yarnpkg.com/@analytics/amplitude/-/amplitude-0.0.3.tgz#15ccb76094d6f1003979a4f3aa5d3263781bd776" integrity sha512-VVJWK3rth+Ak3PiyyzLAz/TUsvhToVXJ6ejvtEIggnNE9bwLDVUHak76MeNlBAS/CCW1SzkWcjbKPpYnnn5aLw== -"@analytics/cookie-utils@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@analytics/cookie-utils/-/cookie-utils-0.2.3.tgz#e6ab923f88d89f7b02da0cfab585ff193977052f" - integrity sha512-RiMAVpSluRbWb2hlT9wMJ0r2l+MUZzScYjY+w2iWRzjOr9Zzzs4tYzJT6Sd94PDz3LzCuf4aGOwS6pkKXTEBLw== +"@analytics/cookie-utils@^0.2.12": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@analytics/cookie-utils/-/cookie-utils-0.2.12.tgz#acc38dd76ead968050776fb8e57e571e6d37cbc7" + integrity sha512-2h/yuIu3kmu+ZJlKmlT6GoRvUEY2k1BbQBezEv5kGhnn9KpmzPz715Y3GmM2i+m7Y0QmBdVUoA260dQZkofs2A== + dependencies: + "@analytics/global-storage-utils" "^0.1.7" + +"@analytics/core@^0.12.7": + version "0.12.7" + resolved "https://registry.yarnpkg.com/@analytics/core/-/core-0.12.7.tgz#118b25f1753796a7c73ffabd4b789219d511e050" + integrity sha512-etmIPCoxWLoUZ/o1o2zvIk4cdVHa8I1xUQtTuLA+YXQ4SsFbm75ZoMXJBqWrNSENpqCJgoL6hizl5uTbkNN+1Q== + dependencies: + "@analytics/global-storage-utils" "^0.1.7" + "@analytics/type-utils" "^0.6.2" + analytics-utils "^1.0.12" -"@analytics/core@^0.10.5": - version "0.10.5" - resolved "https://registry.yarnpkg.com/@analytics/core/-/core-0.10.5.tgz#655f62a77e2290750439cfcd76a840e13ca3c480" - integrity sha512-R2W8ybinHXVnWeVLsvI/+ukHzgCWSRT7EoIi6afbWcAsotneFE6vwLwGAKbWIdnGITl1ZaYU6i6wquF6nfF9sQ== +"@analytics/global-storage-utils@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@analytics/global-storage-utils/-/global-storage-utils-0.1.7.tgz#c6a12eb133a6e44101b7c3529c82e3e89ac9ce46" + integrity sha512-V+spzGLZYm4biZT4uefaylm80SrLXf8WOTv9hCgA46cLcyxx3LD4GCpssp1lj+RcWLl/uXJQBRO4Mnn/o1x6Gw== dependencies: - analytics-utils "^0.4.4" + "@analytics/type-utils" "^0.6.2" "@analytics/google-analytics@^0.5.2": version "0.5.2" @@ -34,17 +45,40 @@ dependencies: universal-analytics "^0.4.20" +"@analytics/localstorage-utils@^0.1.10": + version "0.1.10" + resolved "https://registry.yarnpkg.com/@analytics/localstorage-utils/-/localstorage-utils-0.1.10.tgz#8e9b03604e79a530e9a5ab6748c8ceb96153b95c" + integrity sha512-uJS+Jp1yLG5VFCgA5T82ZODYBS0xuDQx0NtAZrgbqt9j51BX3TcgmOez5LVkrUNu/lpbxjCLq35I4TKj78VmOQ== + dependencies: + "@analytics/global-storage-utils" "^0.1.7" + "@analytics/mixpanel@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@analytics/mixpanel/-/mixpanel-0.3.1.tgz#d14264774302b1b2039115ebe3d5dbe838376081" integrity sha512-zYtzBUdcza/tAT1if6CN0s+BAqtrA2k17WoMFfi6nrLYEj8V60h/o3l+6RUDyIfIg1GkoUhiAJVxJvxW+CMnCw== -"@analytics/storage-utils@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@analytics/storage-utils/-/storage-utils-0.2.5.tgz#bc82a1b5dea8e47ae18718aae687c3408ae7c504" - integrity sha512-RJdKjR4O86eB5fIfApFfhN8Be/Q709DQiRA7UyS0Ymo6w+usnPPxpm6GaKHVop5CIn3vtlMuUxRA4qZhhBrfMw== +"@analytics/session-storage-utils@^0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@analytics/session-storage-utils/-/session-storage-utils-0.0.7.tgz#e355c60b14d4fbcf20983e5cfcb7cb838b4c57ab" + integrity sha512-PSv40UxG96HVcjY15e3zOqU2n8IqXnH8XvTkg1X43uXNTKVSebiI2kUjA3Q7ESFbw5DPwcLbJhV7GforpuBLDw== + dependencies: + "@analytics/global-storage-utils" "^0.1.7" + +"@analytics/storage-utils@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@analytics/storage-utils/-/storage-utils-0.4.2.tgz#222717832a533a1a2516aa3a22d5db80d14a881b" + integrity sha512-AXObwyVQw9h2uJh1t2hUgabtVxzYpW+7uKVbdHQK80vr3Td5rrmCxrCxarh7HUuAgSDZ0bZWqmYxVgmwKceaLg== dependencies: - "@analytics/cookie-utils" "^0.2.3" + "@analytics/cookie-utils" "^0.2.12" + "@analytics/global-storage-utils" "^0.1.7" + "@analytics/localstorage-utils" "^0.1.10" + "@analytics/session-storage-utils" "^0.0.7" + "@analytics/type-utils" "^0.6.2" + +"@analytics/type-utils@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@analytics/type-utils/-/type-utils-0.6.2.tgz#60d706603a98a95681d4b1e9726c703fdd541a9e" + integrity sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg== "@ant-design/colors@6.0.0", "@ant-design/colors@^6.0.0": version "6.0.0" @@ -5691,21 +5725,21 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -analytics-utils@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/analytics-utils/-/analytics-utils-0.4.4.tgz#0fc032c8d3dd8a37f6275ea47f678958204d5bf3" - integrity sha512-MJ6sT28L9RdLIxf/rrcfoDmnfWNxmDlF32q5SKbsce+KRPUPu+BuAp4IUUMgM+nYKWZAsxjI/piFXWqOv97awQ== +analytics-utils@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/analytics-utils/-/analytics-utils-1.0.12.tgz#07bd63471d238e80f42d557fba039365f09c50db" + integrity sha512-WvV2YWgsnXLxaY0QYux0crpBAg/0JA763NmbMVz22jKhMPo7dpTBet8G2IlF7ixTjLDzGlkHk1ZaKqqQmjJ+4w== dependencies: - "@analytics/storage-utils" "^0.2.5" + "@analytics/type-utils" "^0.6.2" dlv "^1.1.3" -analytics@^0.7.5: - version "0.7.5" - resolved "https://registry.yarnpkg.com/analytics/-/analytics-0.7.5.tgz#c65deb0605e6db840415c5f371f894d3dc627919" - integrity sha512-qOQuczBCux574jxfksdVMhD0in9iw8L7PEEjZ/h/OEolbY2UBpFXqydOSyNRG+oF28bBlSPaDQDc3g8f2CwhKA== +analytics@^0.8.9: + version "0.8.9" + resolved "https://registry.yarnpkg.com/analytics/-/analytics-0.8.9.tgz#71648ec804fbf01f05abbd0e27bc11049d959786" + integrity sha512-oTbUzQpncMTslakqfK70GgB6bopk5hY+uuekwnadMkDyqNLgcD02KRzteTnO7q5Ko6wDECVtT8xi/6OuAMZykA== dependencies: - "@analytics/core" "^0.10.5" - "@analytics/storage-utils" "^0.2.5" + "@analytics/core" "^0.12.7" + "@analytics/storage-utils" "^0.4.2" ansi-colors@^3.0.0: version "3.2.4" diff --git a/docker/airflow/local_airflow.md b/docker/airflow/local_airflow.md index d0a2b18cff2d27..55a64f5c122c51 100644 --- a/docker/airflow/local_airflow.md +++ b/docker/airflow/local_airflow.md @@ -138,25 +138,57 @@ Successfully added `conn_id`=datahub_rest_default : datahub_rest://:@http://data Navigate the Airflow UI to find the sample Airflow dag we just brought in -![Find the DAG](../../docs/imgs/airflow/find_the_dag.png) + +

+ +

+ By default, Airflow loads all DAG-s in paused status. Unpause the sample DAG to use it. -![Paused DAG](../../docs/imgs/airflow/paused_dag.png) -![Unpaused DAG](../../docs/imgs/airflow/unpaused_dag.png) + +

+ +

+ + +

+ +

+ Then trigger the DAG to run. -![Trigger the DAG](../../docs/imgs/airflow/trigger_dag.png) + +

+ +

+ After the DAG runs successfully, go over to your DataHub instance to see the Pipeline and navigate its lineage. -![DataHub Pipeline View](../../docs/imgs/airflow/datahub_pipeline_view.png) -![DataHub Pipeline Entity](../../docs/imgs/airflow/datahub_pipeline_entity.png) +

+ +

+ + + +

+ +

-![DataHub Task View](../../docs/imgs/airflow/datahub_task_view.png) -![DataHub Lineage View](../../docs/imgs/airflow/datahub_lineage_view.png) + +

+ +

+ + + +

+ +

+ ## TroubleShooting @@ -164,9 +196,17 @@ Most issues are related to connectivity between Airflow and DataHub. Here is how you can debug them. -![Find the Task Log](../../docs/imgs/airflow/finding_failed_log.png) -![Inspect the Log](../../docs/imgs/airflow/connection_error.png) +

+ +

+ + + +

+ +

+ In this case, clearly the connection `datahub-rest` has not been registered. Looks like we forgot to register the connection with Airflow! Let's execute Step 4 to register the datahub connection with Airflow. @@ -175,4 +215,8 @@ In case the connection was registered successfully but you are still seeing `Fai After re-running the DAG, we see success! -![Pipeline Success](../../docs/imgs/airflow/successful_run.png) + +

+ +

+ diff --git a/docker/datahub-frontend/Dockerfile b/docker/datahub-frontend/Dockerfile index 23c04972209ed4..9efc0d2ce8753e 100644 --- a/docker/datahub-frontend/Dockerfile +++ b/docker/datahub-frontend/Dockerfile @@ -29,6 +29,8 @@ FROM base as dev-install VOLUME [ "/datahub-frontend" ] FROM ${APP_ENV}-install as final +COPY ./docker/datahub-frontend/start.sh / +RUN chown datahub:datahub /start.sh && chmod 755 /start.sh USER datahub ARG SERVER_PORT=9002 @@ -37,5 +39,4 @@ RUN echo $SERVER_PORT EXPOSE $SERVER_PORT HEALTHCHECK --start-period=2m --retries=4 CMD curl --fail http://localhost:$SERVER_PORT/admin || exit 1 -COPY ./docker/datahub-frontend/start.sh / CMD ./start.sh diff --git a/docker/datahub-frontend/start.sh b/docker/datahub-frontend/start.sh index a1548670309b53..9dc1514144bb1a 100755 --- a/docker/datahub-frontend/start.sh +++ b/docker/datahub-frontend/start.sh @@ -26,6 +26,21 @@ if [[ ! -z ${SSL_TRUSTSTORE_PASSWORD:-} ]]; then TRUSTSTORE_PASSWORD="-Djavax.net.ssl.trustStorePassword=$SSL_TRUSTSTORE_PASSWORD" fi +HTTP_PROXY="" +if [[ ! -z ${HTTP_PROXY_HOST:-} ]] && [[ ! -z ${HTTP_PROXY_PORT:-} ]]; then + HTTP_PROXY="-Dhttp.proxyHost=$HTTP_PROXY_HOST -Dhttp.proxyPort=$HTTP_PROXY_PORT" +fi + +HTTPS_PROXY="" +if [[ ! -z ${HTTPS_PROXY_HOST:-} ]] && [[ ! -z ${HTTPS_PROXY_PORT:-} ]]; then + HTTPS_PROXY="-Dhttps.proxyHost=$HTTPS_PROXY_HOST -Dhttps.proxyPort=$HTTPS_PROXY_PORT" +fi + +NO_PROXY="" +if [[ ! -z ${HTTP_NON_PROXY_HOSTS:-} ]]; then + NO_PROXY="-Dhttp.nonProxyHosts='$HTTP_NON_PROXY_HOSTS'" +fi + # make sure there is no whitespace at the beginning and the end of # this string export JAVA_OPTS="-Xms512m \ @@ -37,6 +52,7 @@ export JAVA_OPTS="-Xms512m \ -Dlogback.debug=false \ ${PROMETHEUS_AGENT:-} ${OTEL_AGENT:-} \ ${TRUSTSTORE_FILE:-} ${TRUSTSTORE_TYPE:-} ${TRUSTSTORE_PASSWORD:-} \ + ${HTTP_PROXY:-} ${HTTPS_PROXY:-} ${NO_PROXY:-} \ -Dpidfile.path=/dev/null" exec ./datahub-frontend/bin/datahub-frontend diff --git a/docker/datahub-gms/env/docker.postgres.env b/docker/datahub-gms/env/docker.postgres.env index 25d31afa25804a..529be3323a4d99 100644 --- a/docker/datahub-gms/env/docker.postgres.env +++ b/docker/datahub-gms/env/docker.postgres.env @@ -1,25 +1,7 @@ -DATAHUB_UPGRADE_HISTORY_KAFKA_CONSUMER_GROUP_ID=generic-duhe-consumer-job-client-gms -EBEAN_DATASOURCE_USERNAME=datahub -EBEAN_DATASOURCE_PASSWORD=datahub EBEAN_DATASOURCE_HOST=postgres:5432 EBEAN_DATASOURCE_URL=jdbc:postgresql://postgres:5432/datahub EBEAN_DATASOURCE_DRIVER=org.postgresql.Driver + # Uncomment EBEAN_POSTGRES_USE_AWS_IAM_AUTH below to add support for IAM authentication for Postgres. # Password is not required when accessing Postgres using IAM auth. It can be replaced by dummy password # EBEAN_POSTGRES_USE_AWS_IAM_AUTH=true -KAFKA_BOOTSTRAP_SERVER=broker:29092 -KAFKA_SCHEMAREGISTRY_URL=http://schema-registry:8081 -# KAFKA_SCHEMAREGISTRY_URL=http://datahub-gms:8080/schema-registry/api/ -ELASTICSEARCH_HOST=elasticsearch -ELASTICSEARCH_PORT=9200 -ES_BULK_REFRESH_POLICY=WAIT_UNTIL -ELASTICSEARCH_INDEX_BUILDER_SETTINGS_REINDEX=true -ELASTICSEARCH_INDEX_BUILDER_MAPPINGS_REINDEX=true -NEO4J_HOST=http://neo4j:7474 -NEO4J_URI=bolt://neo4j -NEO4J_USERNAME=neo4j -NEO4J_PASSWORD=datahub -MAE_CONSUMER_ENABLED=true -MCE_CONSUMER_ENABLED=true -JAVA_OPTS=-Xms1g -Xmx1g -ENTITY_REGISTRY_CONFIG_PATH=/datahub/datahub-gms/resources/entity-registry.yml diff --git a/docker/datahub-ingestion-base/smoke.Dockerfile b/docker/datahub-ingestion-base/smoke.Dockerfile index 276f6dbc4436e2..15dc46ae5b882a 100644 --- a/docker/datahub-ingestion-base/smoke.Dockerfile +++ b/docker/datahub-ingestion-base/smoke.Dockerfile @@ -20,7 +20,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-11-jdk COPY . /datahub-src ARG RELEASE_VERSION RUN cd /datahub-src/metadata-ingestion && \ - sed -i.bak "s/__version__ = \"0.0.0.dev0\"/__version__ = \"$RELEASE_VERSION\"/" src/datahub/__init__.py && \ + sed -i.bak "s/__version__ = \"1!0.0.0.dev0\"/__version__ = \"$RELEASE_VERSION\"/" src/datahub/__init__.py && \ cat src/datahub/__init__.py && \ cd ../ && \ ./gradlew :metadata-ingestion:installAll diff --git a/docker/datahub-ingestion/Dockerfile b/docker/datahub-ingestion/Dockerfile index 0ecc30d02ac3f7..8b726df5e88420 100644 --- a/docker/datahub-ingestion/Dockerfile +++ b/docker/datahub-ingestion/Dockerfile @@ -7,10 +7,12 @@ FROM $BASE_IMAGE:$DOCKER_VERSION as base USER 0 COPY ./metadata-ingestion /datahub-ingestion +COPY ./metadata-ingestion-modules/airflow-plugin /datahub-ingestion/airflow-plugin ARG RELEASE_VERSION WORKDIR /datahub-ingestion -RUN sed -i.bak "s/__version__ = \"0.0.0.dev0\"/__version__ = \"$RELEASE_VERSION\"/" src/datahub/__init__.py && \ +RUN sed -i.bak "s/__version__ = \"1!0.0.0.dev0\"/__version__ = \"$RELEASE_VERSION\"/" src/datahub/__init__.py && \ + sed -i.bak "s/__version__ = \"1!0.0.0.dev0\"/__version__ = \"$RELEASE_VERSION\"/" airflow-plugin/src/datahub_airflow_plugin/__init__.py && \ cat src/datahub/__init__.py && \ chown -R datahub /datahub-ingestion @@ -21,7 +23,9 @@ FROM base as slim-install RUN pip install --no-cache --user ".[base,datahub-rest,datahub-kafka,snowflake,bigquery,redshift,mysql,postgres,hive,clickhouse,glue,dbt,looker,lookml,tableau,powerbi,superset,datahub-business-glossary]" FROM base as full-install -RUN pip install --no-cache --user ".[all]" +RUN pip install --no-cache --user ".[base]" && \ + pip install --no-cache --user "./airflow-plugin[acryl-datahub-airflow-plugin]" && \ + pip install --no-cache --user ".[all]" FROM base as dev-install # Dummy stage for development. Assumes code is built on your machine and mounted to this image. diff --git a/docker/datahub-ingestion/Dockerfile-slim-only b/docker/datahub-ingestion/Dockerfile-slim-only new file mode 100644 index 00000000000000..9ae116f839aa07 --- /dev/null +++ b/docker/datahub-ingestion/Dockerfile-slim-only @@ -0,0 +1,25 @@ +# Defining environment +ARG BASE_IMAGE=acryldata/datahub-ingestion-base +ARG DOCKER_VERSION=latest + +FROM $BASE_IMAGE:$DOCKER_VERSION as base +USER 0 + +COPY ./metadata-ingestion /datahub-ingestion + +ARG RELEASE_VERSION +WORKDIR /datahub-ingestion +RUN sed -i.bak "s/__version__ = \"1!0.0.0.dev0\"/__version__ = \"$RELEASE_VERSION\"/" src/datahub/__init__.py && \ + cat src/datahub/__init__.py && \ + chown -R datahub /datahub-ingestion + +USER datahub +ENV PATH="/datahub-ingestion/.local/bin:$PATH" + +FROM base as slim-install +RUN pip install --no-cache --user ".[base,datahub-rest,datahub-kafka,snowflake,bigquery,redshift,mysql,postgres,hive,clickhouse,glue,dbt,looker,lookml,tableau,powerbi,superset,datahub-business-glossary]" + +FROM slim-install as final + +USER datahub +ENV PATH="/datahub-ingestion/.local/bin:$PATH" diff --git a/docker/datahub-ingestion/build.gradle b/docker/datahub-ingestion/build.gradle index 22531c0c4fd0ed..307594018c92e6 100644 --- a/docker/datahub-ingestion/build.gradle +++ b/docker/datahub-ingestion/build.gradle @@ -19,18 +19,19 @@ dependencies { docker { name "${docker_registry}/${docker_repo}:v${version}-slim" version "v${version}-slim" - dockerfile file("${rootProject.projectDir}/docker/${docker_dir}/Dockerfile") + dockerfile file("${rootProject.projectDir}/docker/${docker_dir}/Dockerfile-slim-only") files fileTree(rootProject.projectDir) { include "docker/${docker_dir}/*" include "metadata-ingestion/**" + include "metadata-ingestion-modules/**" }.exclude { i -> i.file.isHidden() || i.file == buildDir || - i.file == project(':metadata-ingestion').buildDir + i.file == project(':metadata-ingestion').buildDir || + i.file == project(':metadata-ingestion-modules').buildDir } buildArgs([DOCKER_VERSION: version, - RELEASE_VERSION: version.replace('-SNAPSHOT', '').replace('v', '').replace('-slim', ''), - APP_ENV: 'slim']) + RELEASE_VERSION: version.replace('-SNAPSHOT', '').replace('v', '').replace('-slim', '')]) } tasks.getByName('docker').dependsOn(['build', ':docker:datahub-ingestion-base:docker', diff --git a/docker/datahub-upgrade/env/docker.postgres.env b/docker/datahub-upgrade/env/docker.postgres.env new file mode 100644 index 00000000000000..529be3323a4d99 --- /dev/null +++ b/docker/datahub-upgrade/env/docker.postgres.env @@ -0,0 +1,7 @@ +EBEAN_DATASOURCE_HOST=postgres:5432 +EBEAN_DATASOURCE_URL=jdbc:postgresql://postgres:5432/datahub +EBEAN_DATASOURCE_DRIVER=org.postgresql.Driver + +# Uncomment EBEAN_POSTGRES_USE_AWS_IAM_AUTH below to add support for IAM authentication for Postgres. +# Password is not required when accessing Postgres using IAM auth. It can be replaced by dummy password +# EBEAN_POSTGRES_USE_AWS_IAM_AUTH=true diff --git a/docker/docker-compose-without-neo4j.postgres.override.yml b/docker/docker-compose-without-neo4j.postgres.override.yml new file mode 100644 index 00000000000000..e4c754b30afd79 --- /dev/null +++ b/docker/docker-compose-without-neo4j.postgres.override.yml @@ -0,0 +1,76 @@ +# Override to use PostgreSQL as a backing store for datahub-gms. +--- +version: '3.9' +services: + datahub-gms: + env_file: + - datahub-gms/env/docker-without-neo4j.env + - datahub-gms/env/docker.postgres.env + environment: + - DATAHUB_SERVER_TYPE=${DATAHUB_SERVER_TYPE:-quickstart} + - DATAHUB_TELEMETRY_ENABLED=${DATAHUB_TELEMETRY_ENABLED:-true} + depends_on: + datahub-upgrade: + condition: service_completed_successfully + volumes: + - ${HOME}/.datahub/plugins:/etc/datahub/plugins + + datahub-upgrade: + container_name: datahub-upgrade + hostname: datahub-upgrade + image: ${DATAHUB_UPGRADE_IMAGE:-acryldata/datahub-upgrade}:${DATAHUB_VERSION:-head} + command: + - -u + - SystemUpdate + build: + context: ../ + dockerfile: docker/datahub-upgrade/Dockerfile + env_file: + - datahub-upgrade/env/docker-without-neo4j.env + - datahub-upgrade/env/docker.postgres.env + depends_on: + postgres-setup: + condition: service_completed_successfully + elasticsearch-setup: + condition: service_completed_successfully + kafka-setup: + condition: service_completed_successfully + + postgres-setup: + container_name: postgres-setup + hostname: postgres-setup + image: ${DATAHUB_POSTGRES_SETUP_IMAGE:-acryldata/datahub-postgres-setup}:${DATAHUB_VERSION:-head} + build: + context: ../ + dockerfile: docker/postgres-setup/Dockerfile + env_file: postgres-setup/env/docker.env + depends_on: + postgres: + condition: service_healthy + labels: + datahub_setup_job: true + + postgres: + container_name: postgres + hostname: postgres + image: postgres:12.3 + env_file: postgres/env/docker.env + ports: + - '5432:5432' + restart: on-failure + healthcheck: + test: [ "CMD-SHELL", "pg_isready" ] + start_period: 20s + interval: 2s + timeout: 10s + retries: 5 + volumes: + - ./init.sql:/docker-entrypoint-initdb.d/init.sql + - postgresdata:/var/lib/postgresql/data + + kafka-setup: + environment: + - DATAHUB_PRECREATE_TOPICS=${DATAHUB_PRECREATE_TOPICS:-false} + +volumes: + postgresdata: diff --git a/docker/docker-compose-without-neo4j.yml b/docker/docker-compose-without-neo4j.yml index a755eda21cbf54..0b2e4f76b8fa9e 100644 --- a/docker/docker-compose-without-neo4j.yml +++ b/docker/docker-compose-without-neo4j.yml @@ -66,8 +66,6 @@ services: dockerfile: docker/datahub-upgrade/Dockerfile env_file: datahub-upgrade/env/docker-without-neo4j.env depends_on: - mysql-setup: - condition: service_completed_successfully elasticsearch-setup: condition: service_completed_successfully kafka-setup: diff --git a/docker/kafka-setup/Dockerfile b/docker/kafka-setup/Dockerfile index 5707234b85f570..a9c75521fead13 100644 --- a/docker/kafka-setup/Dockerfile +++ b/docker/kafka-setup/Dockerfile @@ -15,9 +15,6 @@ FROM python:3-alpine ENV KAFKA_VERSION 3.4.1 ENV SCALA_VERSION 2.13 -# Set the classpath for JARs required by `cub` -ENV CUB_CLASSPATH='"/usr/share/java/cp-base-new/*"' - LABEL name="kafka" version=${KAFKA_VERSION} RUN apk add --no-cache bash coreutils @@ -31,10 +28,6 @@ RUN mkdir -p /opt \ && mv /opt/kafka_${SCALA_VERSION}-${KAFKA_VERSION} /opt/kafka \ && adduser -DH -s /sbin/nologin kafka \ && chown -R kafka: /opt/kafka \ - && echo "===> Installing python packages ..." \ - && pip install --no-cache-dir --upgrade pip wheel setuptools \ - && pip install jinja2 requests \ - && pip install "Cython<3.0" "PyYAML<6" --no-build-isolation \ && rm -rf /tmp/* \ && apk del --purge .build-deps diff --git a/docker/postgres-setup/Dockerfile b/docker/postgres-setup/Dockerfile index 5701427d2d48a4..313615ac3465bb 100644 --- a/docker/postgres-setup/Dockerfile +++ b/docker/postgres-setup/Dockerfile @@ -10,10 +10,10 @@ WORKDIR /go/src/github.com/jwilder/dockerize RUN go install github.com/jwilder/dockerize@$DOCKERIZE_VERSION FROM alpine:3 +COPY --from=binary /go/bin/dockerize /usr/local/bin # PFP-260: Upgrade Sqlite to >=3.28.0-r0 to fix https://security.snyk.io/vuln/SNYK-ALPINE39-SQLITE-449762 RUN apk add --no-cache postgresql-client sqlite -COPY --from=binary /go/bin/dockerize /usr/local/bin COPY docker/postgres-setup/init.sql /init.sql COPY docker/postgres-setup/init.sh /init.sh diff --git a/docker/postgres/docker-compose.postgres.yml b/docker/postgres/docker-compose.postgres.yml deleted file mode 100644 index 5eaf9478932b51..00000000000000 --- a/docker/postgres/docker-compose.postgres.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Override to use PostgreSQL as a backing store for datahub-gms. ---- -version: '3.8' -services: - postgres: - container_name: postgres - hostname: postgres - image: postgres:12.3 - env_file: env/docker.env - ports: - - '5432:5432' - volumes: - - ./init.sql:/docker-entrypoint-initdb.d/init.sql - - datahub-gms: - env_file: ../datahub-gms/env/dev.postgres.env - depends_on: - - postgres - -networks: - default: - name: datahub_network diff --git a/docker/postgres/env/docker.env b/docker/postgres/env/docker.env index f84a2b56351905..aced4c441222be 100644 --- a/docker/postgres/env/docker.env +++ b/docker/postgres/env/docker.env @@ -1,2 +1,3 @@ POSTGRES_USER: datahub POSTGRES_PASSWORD: datahub +PGUSER: datahub diff --git a/docker/postgres/init.sql b/docker/postgres/init.sql index 4da8adaf8a6da0..cf477c135422e8 100644 --- a/docker/postgres/init.sql +++ b/docker/postgres/init.sql @@ -11,7 +11,7 @@ create table metadata_aspect_v2 ( constraint pk_metadata_aspect_v2 primary key (urn,aspect,version) ); -create index timeIndex ON metadata_aspect_v2 (createdon); +create index if not exists timeIndex ON metadata_aspect_v2 (createdon); insert into metadata_aspect_v2 (urn, aspect, version, metadata, createdon, createdby) values( 'urn:li:corpuser:datahub', diff --git a/docs-website/build.gradle b/docs-website/build.gradle index 12f37033efc2f7..a213ec1ae8194d 100644 --- a/docs-website/build.gradle +++ b/docs-website/build.gradle @@ -77,14 +77,19 @@ task yarnGenerate(type: YarnTask, dependsOn: [yarnInstall, args = ['run', 'generate'] } -task yarnStart(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate]) { +task downloadHistoricalVersions(type: Exec) { + workingDir '.' + commandLine 'python3', 'download_historical_versions.py' +} + +task yarnStart(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate, downloadHistoricalVersions]) { args = ['run', 'start'] } task fastReload(type: YarnTask) { args = ['run', 'generate-rsync'] } -task yarnLint(type: YarnTask, dependsOn: [yarnInstall]) { +task yarnLint(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate]) { inputs.files(projectMdFiles) args = ['run', 'lint-check'] outputs.dir("dist") @@ -105,7 +110,7 @@ task serve(type: YarnTask, dependsOn: [yarnInstall] ) { } -task yarnBuild(type: YarnTask, dependsOn: [yarnLint, yarnGenerate]) { +task yarnBuild(type: YarnTask, dependsOn: [yarnLint, yarnGenerate, downloadHistoricalVersions]) { inputs.files(projectMdFiles) inputs.file("package.json").withPathSensitivity(PathSensitivity.RELATIVE) inputs.dir("src").withPathSensitivity(PathSensitivity.RELATIVE) @@ -114,6 +119,10 @@ task yarnBuild(type: YarnTask, dependsOn: [yarnLint, yarnGenerate]) { outputs.dir("dist") // tell gradle to apply the build cache outputs.cacheIf { true } + // See https://stackoverflow.com/questions/53230823/fatal-error-ineffective-mark-compacts-near-heap-limit-allocation-failed-java + // and https://github.com/facebook/docusaurus/issues/8329. + // TODO: As suggested in https://github.com/facebook/docusaurus/issues/4765, try switching to swc-loader. + environment = ['NODE_OPTIONS': '--max-old-space-size=10248'] args = ['run', 'build'] } diff --git a/docs-website/docusaurus.config.js b/docs-website/docusaurus.config.js index c10c178424b53f..9bdba5f3175426 100644 --- a/docs-website/docusaurus.config.js +++ b/docs-website/docusaurus.config.js @@ -69,6 +69,11 @@ module.exports = { label: "Roadmap", position: "right", }, + { + type: 'docsVersionDropdown', + position: 'right', + dropdownActiveClassDisabled: true, + }, { href: "https://slack.datahubproject.io", "aria-label": "Slack", @@ -173,8 +178,8 @@ module.exports = { appId: "RK0UG797F3", apiKey: "39d7eb90d8b31d464e309375a52d674f", indexName: "datahubproject", - // contextualSearch: true, - // searchParameters: {}, + insights: true, + contextualSearch: true, // debug: true, }, }, diff --git a/docs-website/download_historical_versions.py b/docs-website/download_historical_versions.py new file mode 100644 index 00000000000000..83157edc1972cf --- /dev/null +++ b/docs-website/download_historical_versions.py @@ -0,0 +1,78 @@ +import json +import os +import tarfile +import urllib.request + +repo_url = "https://api.github.com/repos/datahub-project/static-assets" + + +def download_file(url, destination): + with urllib.request.urlopen(url) as response: + with open(destination, "wb") as f: + while True: + chunk = response.read(8192) + if not chunk: + break + f.write(chunk) + + +def fetch_urls(repo_url: str, folder_path: str, file_format: str): + api_url = f"{repo_url}/contents/{folder_path}" + response = urllib.request.urlopen(api_url) + data = response.read().decode("utf-8") + urls = [ + file["download_url"] + for file in json.loads(data) + if file["name"].endswith(file_format) + ] + print(urls) + return urls + + +def extract_tar_file(destination_path): + with tarfile.open(destination_path, "r:gz") as tar: + tar.extractall() + os.remove(destination_path) + + +def download_versioned_docs(folder_path: str, destination_dir: str, file_format: str): + if not os.path.exists(destination_dir): + os.makedirs(destination_dir) + + urls = fetch_urls(repo_url, folder_path, file_format) + + for url in urls: + filename = os.path.basename(url) + destination_path = os.path.join(destination_dir, filename) + + version = ".".join(filename.split(".")[:3]) + extracted_path = os.path.join(destination_dir, version) + print("extracted_path", extracted_path) + if os.path.exists(extracted_path): + print(f"{extracted_path} already exists, skipping downloads") + continue + try: + download_file(url, destination_path) + print(f"Downloaded {filename} to {destination_dir}") + if file_format == ".tar.gz": + extract_tar_file(destination_path) + except urllib.error.URLError as e: + print(f"Error while downloading {filename}: {e}") + continue + + +def main(): + download_versioned_docs( + folder_path="versioned_docs", + destination_dir="versioned_docs", + file_format=".tar.gz", + ) + download_versioned_docs( + folder_path="versioned_sidebars", + destination_dir="versioned_sidebars", + file_format=".json", + ) + + +if __name__ == "__main__": + main() diff --git a/docs-website/filterTagIndexes.json b/docs-website/filterTagIndexes.json index a86262731fc9a5..c154b586fe66e3 100644 --- a/docs-website/filterTagIndexes.json +++ b/docs-website/filterTagIndexes.json @@ -88,6 +88,17 @@ "Features": "Stateful Ingestion, Column Level Lineage, UI Ingestion, Status Aspect" } }, + { + "Path": "docs/generated/ingestion/sources/datahub", + "imgPath": "img/acryl-logo-light-mark.png", + "Title": "DataHub", + "Description": "Integrate your open source DataHub instance with Acryl Cloud or other on-prem DataHub instances", + "tags": { + "Platform Type": "Metadata", + "Connection Type": "Pull", + "Features": "Stateful Ingestion" + } + }, { "Path": "docs/generated/ingestion/sources/dbt", "imgPath": "img/logos/platforms/dbt.svg", diff --git a/docs-website/generateDocsDir.ts b/docs-website/generateDocsDir.ts index ee6e6b586615c2..892d02c43fe977 100644 --- a/docs-website/generateDocsDir.ts +++ b/docs-website/generateDocsDir.ts @@ -1,5 +1,5 @@ import { execSync } from "child_process"; -import * as matter from "gray-matter"; +import matter from "gray-matter"; import * as fs from "fs"; import * as path from "path"; import { Octokit } from "@octokit/rest"; @@ -26,7 +26,7 @@ const sidebars_text = fs.readFileSync(SIDEBARS_DEF_PATH).toString(); const MyOctokit = Octokit.plugin(retry).plugin(throttling); const octokit = new MyOctokit({ throttle: { - onRateLimit: (retryAfter, options) => { + onRateLimit: (retryAfter: number, options: any) => { // Retry twice after rate limit is hit. if (options.request.retryCount <= 2) { return true; @@ -157,7 +157,7 @@ function get_slug(filepath: string): string { // There's no need to do this cleanup, but it does make the URLs a bit more aesthetic. if (filepath in hardcoded_slugs) { - return hardcoded_slugs[filepath]; + return hardcoded_slugs[filepath as keyof typeof hardcoded_slugs]; } let slug = get_id(filepath); @@ -218,9 +218,10 @@ function markdown_guess_title( let title: string; if (filepath in hardcoded_titles) { - title = hardcoded_titles[filepath]; + title = hardcoded_titles[filepath as keyof typeof hardcoded_titles]; if (filepath in hardcoded_descriptions) { - contents.data.description = hardcoded_descriptions[filepath]; + contents.data.description = + hardcoded_descriptions[filepath as keyof typeof hardcoded_descriptions]; } if (hardcoded_hide_title.includes(filepath)) { contents.data.hide_title = true; diff --git a/docs-website/markdown-link-check-config.json b/docs-website/markdown-link-check-config.json new file mode 100644 index 00000000000000..26e040edde6f79 --- /dev/null +++ b/docs-website/markdown-link-check-config.json @@ -0,0 +1,50 @@ +{ + "ignorePatterns": [ + { + "pattern": "^http://demo\\.datahubproject\\.io" + }, + { + "pattern": "^http://localhost" + }, + { + "pattern": "^http://www.famfamfam.com" + }, + { + "pattern": "^http://www.linkedin.com" + }, + { + "pattern": "\\.md$" + }, + { + "pattern":"\\.json$" + }, + { + "pattern":"\\.txt$" + }, + { + "pattern": "\\.java$" + }, + { + "pattern": "\\.md#.*$" + }, + { + "pattern": "^https://oauth2.googleapis.com/token" + }, + { + "pattern": "^https://login.microsoftonline.com/common/oauth2/na$" + }, + { + "pattern": "#v(\\d+)-(\\d+)-(\\d+)" + }, + { + "pattern": "^https://github.com/mohdsiddique$" + }, + { + "pattern": "^https://github.com/2x$" + }, + { + "pattern": "^https://github.com/datahub-project/datahub/assets/15873986/2f47d033-6c2b-483a-951d-e6d6b807f0d0%22%3E$" + } + ], + "aliveStatusCodes": [200, 206, 0, 999, 400, 401, 403] +} \ No newline at end of file diff --git a/docs-website/package.json b/docs-website/package.json index f382b5e29905ca..1722f921696927 100644 --- a/docs-website/package.json +++ b/docs-website/package.json @@ -17,29 +17,32 @@ "generate": "rm -rf genDocs genStatic && mkdir genDocs genStatic && yarn _generate-docs && mv docs/* genDocs/ && rmdir docs", "generate-rsync": "mkdir -p genDocs genStatic && yarn _generate-docs && rsync -v --checksum -r -h -i --delete docs/ genDocs && rm -rf docs", "lint": "prettier -w generateDocsDir.ts sidebars.js src/pages/index.js", - "lint-check": "prettier -l generateDocsDir.ts sidebars.js src/pages/index.js", + "lint-check": "prettier -l generateDocsDir.ts sidebars.js src/pages/index.js && find ./genDocs -name \\*.md -not -path \"./genDocs/python-sdk/models.md\" -print0 | xargs -0 -n1 markdown-link-check -p -q -c markdown-link-check-config.json", "lint-fix": "prettier --write generateDocsDir.ts sidebars.js src/pages/index.js" }, "dependencies": { "@ant-design/icons": "^4.7.0", - "@docusaurus/core": "^2.1.0", - "@docusaurus/plugin-content-docs": "^2.1.0", - "@docusaurus/plugin-ideal-image": "^2.1.0", - "@docusaurus/preset-classic": "^2.1.0", + "@docusaurus/core": "^2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-ideal-image": "^2.4.1", + "@docusaurus/preset-classic": "^2.4.1", "@markprompt/react": "^0.3.5", "@octokit/plugin-retry": "^3.0.9", "@octokit/plugin-throttling": "^3.5.1", "@octokit/rest": "^18.6.2", "@radix-ui/react-visually-hidden": "^1.0.2", + "@supabase/supabase-js": "^2.33.1", "antd": "^5.0.7", "clsx": "^1.1.1", "docusaurus-graphql-plugin": "0.5.0", "docusaurus-plugin-sass": "^0.2.1", "dotenv": "^16.0.1", + "markdown-link-check": "^3.11.2", "markprompt": "^0.1.7", "react": "^18.2.0", "react-dom": "18.2.0", - "sass": "^1.43.2" + "sass": "^1.43.2", + "uuid": "^9.0.0" }, "browserslist": { "production": [ @@ -55,7 +58,7 @@ }, "devDependencies": { "prettier": "^2.3.0", - "ts-node": "^9.1.1", + "ts-node": "^10.9.1", "typescript": "^4.1.5" } } diff --git a/docs-website/sidebars.js b/docs-website/sidebars.js index 51a57fc41dd364..12691e9f8268a5 100644 --- a/docs-website/sidebars.js +++ b/docs-website/sidebars.js @@ -138,7 +138,15 @@ module.exports = { ], }, { - Deployment: [ + type: "category", + label: "Deployment", + link: { + type: "generated-index", + title: "Deployment Guides", + description: + "Learn how to deploy DataHub to your environment, set up authentication, manage upgrades, and more.", + }, + items: [ // The purpose of this section is to provide the minimum steps required to deploy DataHub to the vendor of your choosing "docs/deploy/aws", "docs/deploy/gcp", @@ -160,6 +168,7 @@ module.exports = { "docs/authentication/guides/sso/configure-oidc-react-google", "docs/authentication/guides/sso/configure-oidc-react-okta", "docs/authentication/guides/sso/configure-oidc-react-azure", + "docs/authentication/guides/sso/configure-oidc-behind-proxy", ], }, ], @@ -395,7 +404,14 @@ module.exports = { ], }, { - Features: [ + type: "category", + label: "Features", + link: { + type: "generated-index", + title: "Feature Guides", + description: "Learn about the features of DataHub.", + }, + items: [ "docs/ui-ingestion", "docs/how/search", "docs/schema-history", @@ -418,7 +434,10 @@ module.exports = { }, "docs/act-on-metadata/impact-analysis", { - Observability: ["docs/managed-datahub/observe/freshness-assertions"], + Observability: [ + "docs/managed-datahub/observe/freshness-assertions", + "docs/managed-datahub/observe/volume-assertions", + ], }, ], }, @@ -578,6 +597,7 @@ module.exports = { }, { "Managed DataHub Release History": [ + "docs/managed-datahub/release-notes/v_0_2_11", "docs/managed-datahub/release-notes/v_0_2_10", "docs/managed-datahub/release-notes/v_0_2_9", "docs/managed-datahub/release-notes/v_0_2_8", diff --git a/docs-website/sphinx/Makefile b/docs-website/sphinx/Makefile index 00ece7ae253317..c01b45e322c679 100644 --- a/docs-website/sphinx/Makefile +++ b/docs-website/sphinx/Makefile @@ -22,7 +22,7 @@ $(VENV_SENTINEL): requirements.txt $(VENV_DIR)/bin/pip install -r requirements.txt touch $(VENV_SENTINEL) -.PHONY: help html doctest linkcheck clean serve md +.PHONY: help html doctest linkcheck clean clean_all serve md # Not using Python's http.server because it enables caching headers. serve: @@ -35,3 +35,6 @@ md: html # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). html doctest linkcheck clean: venv Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +clean_all: clean + -rm -rf $(VENV_DIR) diff --git a/docs-website/sphinx/requirements.txt b/docs-website/sphinx/requirements.txt index a63fd058532599..94ddd40579f0e7 100644 --- a/docs-website/sphinx/requirements.txt +++ b/docs-website/sphinx/requirements.txt @@ -1,4 +1,4 @@ --e ../../metadata-ingestion[datahub-rest] +-e ../../metadata-ingestion[datahub-rest,sql-parsing] beautifulsoup4==4.11.2 Sphinx==6.1.3 sphinx-click==4.4.0 diff --git a/docs-website/src/components/Feedback/index.js b/docs-website/src/components/Feedback/index.js new file mode 100644 index 00000000000000..ecabca445bd48c --- /dev/null +++ b/docs-website/src/components/Feedback/index.js @@ -0,0 +1,102 @@ +import React, { useState, useMemo } from "react"; +import clsx from "clsx"; +import { supabase } from "./supabase"; +import styles from "./styles.module.scss"; +import { LikeOutlined, DislikeOutlined, CheckCircleOutlined } from "@ant-design/icons"; +import { v4 as uuidv4 } from "uuid"; + +const Feedback = () => { + const [reaction, setReaction] = useState(null); + const [feedback, setFeedback] = useState(""); + const [submitted, setSubmitted] = useState(false); + const [reactionId, setReactionId] = useState(null); + + const handleReaction = async (selectedReaction) => { + if (reaction !== selectedReaction) { + const uuid = uuidv4(); + try { + const { error } = await supabase.from("reaction_feedback").insert([ + { + id: uuid, + page: window.location.href, + reaction: selectedReaction, + }, + ]); + + if (error) { + console.error("Error submitting feedback:", error); + return; + } + setReactionId(uuid); + setReaction(selectedReaction); + } catch (error) { + console.error("Error submitting feedback:", error); + } + } else { + setReaction(null); + } + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + try { + if (feedback !== "" && reactionId !== null) { + const { error } = await supabase.from("written_feedback").insert([ + { + feedback: feedback, + reaction_feedback_id: reactionId, + }, + ]); + + if (error) { + console.error("Error submitting feedback:", error); + return; + } + setSubmitted(true); + } + } catch (error) { + console.error("Error submitting feedback:", error); + } + }; + + return ( +
+
+ {!submitted ? ( + <> +
+ Is this page helpful? +
+ + +
+
+ {reaction !== null && ( +
+ + +
+ )} + + ) : ( +
+ + Thanks for your feedback! +
+ )} +
+
+ ); +}; + +export default Feedback; diff --git a/docs-website/src/components/Feedback/styles.module.scss b/docs-website/src/components/Feedback/styles.module.scss new file mode 100644 index 00000000000000..b0fa3d7d1bd2bc --- /dev/null +++ b/docs-website/src/components/Feedback/styles.module.scss @@ -0,0 +1,78 @@ +.feedbackWrapper { + display: flex; +} + +.feedbackWidget { + min-height: 64px; + margin: 15px auto; + padding: 10px 20px; + border: var(--ifm-hr-border-color) 1px solid; + border-radius: 32px; + text-align: center; + display: flex; + justify-content: center; + flex-direction: column; +} + +.feedbackButtons { + strong { + margin-right: 4px; + } + + display: flex; + justify-content: center; + align-items: center; + gap: 1rem; +} + +.feedbackForm { + margin: 1rem 0; + display: flex; + flex-direction: column; + width: 100%; + gap: 0.8rem; + button { + margin-left: auto; + } +} + +.feedbackText { + width: 100%; + border: var(--ifm-hr-border-color) 1px solid; + border-radius: 0.4rem; + padding: 0.4rem; + font-family: "Manrope", sans-serif; +} + +.feedbackButton { + width: 2rem; + height: 2rem; + text-align: center; + font-size: 1.25rem; + padding: 0.25rem; + border-radius: 1000em; + margin-left: 1rem; + cursor: pointer; + transition: all 0.2s ease-in-out; + svg { + fill: var(--ifm-link-color); + } + + &:hover, + &.active { + background: var(--ifm-link-color); + svg { + fill: var(--ifm-background-color); + } + } +} + +.feedbackMessage { + display: flex; + align-items: center; + svg { + font-size: larger; + margin-right: 6px; + fill: var(--ifm-color-success); + } +} diff --git a/docs-website/src/components/Feedback/supabase.js b/docs-website/src/components/Feedback/supabase.js new file mode 100644 index 00000000000000..2f3b8e43065657 --- /dev/null +++ b/docs-website/src/components/Feedback/supabase.js @@ -0,0 +1,9 @@ +import { createClient } from "@supabase/supabase-js"; + +const supabaseUrl = "https://ttydafdojardufehywni.supabase.co"; +const supabaseKey = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InR0eWRhZmRvamFyZHVmZWh5d25pIiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTMzNDk2NDksImV4cCI6MjAwODkyNTY0OX0.X2KKTPFzouQyXAQH3VTrL-fyhbdUtlPsLHIYtoACQss"; + +export const supabase = createClient(supabaseUrl, supabaseKey); + +export default supabase; diff --git a/docs-website/src/pages/docs/_components/SearchBar/index.jsx b/docs-website/src/pages/docs/_components/SearchBar/index.jsx index 37f8a5c252aee6..e3b61fb3cb4764 100644 --- a/docs-website/src/pages/docs/_components/SearchBar/index.jsx +++ b/docs-website/src/pages/docs/_components/SearchBar/index.jsx @@ -18,7 +18,8 @@ import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment"; import { usePluralForm, useEvent } from "@docusaurus/theme-common"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; import { useAllDocsData } from "@docusaurus/plugin-content-docs/client"; -import { useSearchPage } from "@docusaurus/theme-common/internal"; +import { useSearchQueryString } from "@docusaurus/theme-common"; +import { useTitleFormatter } from "@docusaurus/theme-common/internal"; import Translate, { translate } from "@docusaurus/Translate"; import styles from "./search.module.scss"; @@ -47,7 +48,7 @@ function useDocsSearchVersionsHelpers() { // docsPluginId -> versionName map const [searchVersions, setSearchVersions] = useState(() => { return Object.entries(allDocsData).reduce((acc, [pluginId, pluginData]) => { - return { ...acc, [pluginId]: pluginData.versions[0].name }; + return { ...acc, [pluginId]: pluginData.versions?.[1].name }; }, {}); }); @@ -69,11 +70,11 @@ const SearchVersionSelectList = ({ docsSearchVersionsHelpers }) => { const versionedPluginEntries = Object.entries(docsSearchVersionsHelpers.allDocsData) // Do not show a version select for unversioned docs plugin instances .filter(([, docsData]) => docsData.versions.length > 1); - return ( -
+ <> {versionedPluginEntries.map(([pluginId, docsData]) => { const labelPrefix = versionedPluginEntries.length > 1 ? `${pluginId}: ` : ""; + return ( ); })} -
+ ); }; @@ -103,7 +104,7 @@ function SearchBar() { const documentsFoundPlural = useDocumentsFoundPlural(); const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers(); - const { searchQuery, setSearchQuery } = useSearchPage() + const [searchQuery, setSearchQuery] = useSearchQueryString(); const initialSearchResultState = { items: [], query: null, @@ -273,40 +274,40 @@ function SearchBar() { return (
-
e.preventDefault()} className={styles.searchForm}> - setSearchQuery(e.target.value)} - value={searchQuery} - autoComplete="off" - autoFocus - /> - - - - +
+ e.preventDefault()} className={styles.searchForm}> + setSearchQuery(e.target.value)} + value={searchQuery} + autoComplete="off" + autoFocus + /> + + + + {docsSearchVersionsHelpers.versioningEnabled && } - - +
{!!searchResultState.totalResults && documentsFoundPlural(searchResultState.totalResults)}
{searchResultState.items.length > 0 ? ( diff --git a/docs-website/src/pages/docs/_components/SearchBar/search.module.scss b/docs-website/src/pages/docs/_components/SearchBar/search.module.scss index 17e5f224906646..6faaf19c7e6031 100644 --- a/docs-website/src/pages/docs/_components/SearchBar/search.module.scss +++ b/docs-website/src/pages/docs/_components/SearchBar/search.module.scss @@ -5,9 +5,14 @@ * LICENSE file in the root directory of this source tree. */ +.searchHeader { + display: flex; + gap: 0.8rem; +} + .searchForm { position: relative; - + flex: 1; &:focus + svg { color: red; } @@ -21,21 +26,33 @@ height: 1.5rem; } +.searchQueryInput { + padding: 0.8rem 0.8rem 0.8rem 3rem; + width: 100%; +} + +.searchVersionInput { + padding: 0.8rem 2rem 0.8rem 0.8rem; + appearance: none; + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 0.6rem center; + background-size: 1em; +} + .searchQueryInput, .searchVersionInput { border-radius: 1000em; border-style: solid; border-color: transparent; font: var(--ifm-font-size-base) var(--ifm-font-family-base); - padding: 0.8rem 0.8rem 0.8rem 3rem; - width: 100%; - background: var(--docsearch-searchbox-background); + background-color: var(--docsearch-searchbox-background); color: var(--docsearch-text-color); margin-bottom: 0.5rem; transition: border var(--ifm-transition-fast) ease; &:focus { - background: var(--ifm-background-color); + background-color: var(--ifm-background-color); + svg { color: var(--docsearch-primary-color); @@ -91,10 +108,6 @@ } @media only screen and (max-width: 996px) { - .searchVersionColumn { - max-width: 40% !important; - } - .searchResultsColumn { max-width: 60% !important; } @@ -113,9 +126,14 @@ .searchVersionColumn { max-width: 100% !important; padding-left: var(--ifm-spacing-horizontal) !important; + margin: auto; } } +.searchVersionColumn { + margin: auto; +} + .loadingSpinner { width: 3rem; height: 3rem; diff --git a/docs-website/src/theme/DocItem/Footer/index.js b/docs-website/src/theme/DocItem/Footer/index.js new file mode 100644 index 00000000000000..94b6c7734f9eed --- /dev/null +++ b/docs-website/src/theme/DocItem/Footer/index.js @@ -0,0 +1,58 @@ +import React from "react"; +import clsx from "clsx"; +import { ThemeClassNames } from "@docusaurus/theme-common"; +import { useDoc } from "@docusaurus/theme-common/internal"; +import LastUpdated from "@theme/LastUpdated"; +import EditThisPage from "@theme/EditThisPage"; +import TagsListInline from "@theme/TagsListInline"; +import styles from "./styles.module.css"; +import Feedback from "../../../components/Feedback"; + +function TagsRow(props) { + return ( +
+
+ +
+
+ ); +} +function EditMetaRow({ editUrl, lastUpdatedAt, lastUpdatedBy, formattedLastUpdatedAt }) { + return ( +
+
{editUrl && }
+ +
+ {(lastUpdatedAt || lastUpdatedBy) && ( + + )} +
+
+ ); +} +export default function DocItemFooter() { + const { metadata } = useDoc(); + const { editUrl, lastUpdatedAt, formattedLastUpdatedAt, lastUpdatedBy, tags, unversionedId } = metadata; + const canDisplayTagsRow = tags.length > 0; + const canDisplayEditMetaRow = !!(editUrl || lastUpdatedAt || lastUpdatedBy); + const canDisplayFooter = canDisplayTagsRow || canDisplayEditMetaRow; + if (!canDisplayFooter) { + return null; + } + return ( + <> +
+ {canDisplayTagsRow && } + {canDisplayEditMetaRow && ( + + )} +
+ + + ); +} diff --git a/docs-website/src/theme/DocItem/Footer/styles.module.css b/docs-website/src/theme/DocItem/Footer/styles.module.css new file mode 100644 index 00000000000000..7c1e964419179b --- /dev/null +++ b/docs-website/src/theme/DocItem/Footer/styles.module.css @@ -0,0 +1,11 @@ +.lastUpdated { + margin-top: 0.2rem; + font-style: italic; + font-size: smaller; +} + +@media (min-width: 997px) { + .lastUpdated { + text-align: right; + } +} diff --git a/docs-website/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.js b/docs-website/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.js new file mode 100644 index 00000000000000..cc04ab23d3cf37 --- /dev/null +++ b/docs-website/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.js @@ -0,0 +1,70 @@ +import React from "react"; +import { useVersions, useActiveDocContext } from "@docusaurus/plugin-content-docs/client"; +import { useDocsPreferredVersion } from "@docusaurus/theme-common"; +import { useDocsVersionCandidates } from "@docusaurus/theme-common/internal"; +import { translate } from "@docusaurus/Translate"; +import { useLocation } from "@docusaurus/router"; +import DefaultNavbarItem from "@theme/NavbarItem/DefaultNavbarItem"; +import DropdownNavbarItem from "@theme/NavbarItem/DropdownNavbarItem"; +const getVersionMainDoc = (version) => version.docs.find((doc) => doc.id === version.mainDocId); +export default function DocsVersionDropdownNavbarItem({ + mobile, + docsPluginId, + dropdownActiveClassDisabled, + dropdownItemsBefore, + dropdownItemsAfter, + ...props +}) { + const { search, hash } = useLocation(); + const activeDocContext = useActiveDocContext(docsPluginId); + const versions = useVersions(docsPluginId); + const { savePreferredVersionName } = useDocsPreferredVersion(docsPluginId); + const versionLinks = versions.map((version) => { + // We try to link to the same doc, in another version + // When not possible, fallback to the "main doc" of the version + const versionDoc = activeDocContext.alternateDocVersions[version.name] ?? getVersionMainDoc(version); + return { + label: version.label, + // preserve ?search#hash suffix on version switches + to: `${versionDoc.path}${search}${hash}`, + isActive: () => version === activeDocContext.activeVersion, + onClick: () => savePreferredVersionName(version.name), + }; + }); + const items = [...dropdownItemsBefore, ...versionLinks, ...dropdownItemsAfter]; + const dropdownVersion = useDocsVersionCandidates(docsPluginId)[0]; + // Mobile dropdown is handled a bit differently + const dropdownLabel = + mobile && items.length > 1 + ? translate({ + id: "theme.navbar.mobileVersionsDropdown.label", + message: "Versions", + description: "The label for the navbar versions dropdown on mobile view", + }) + : dropdownVersion.label; + const dropdownTo = mobile && items.length > 1 ? undefined : getVersionMainDoc(dropdownVersion).path; + // We don't want to render a version dropdown with 0 or 1 item. If we build + // the site with a single docs version (onlyIncludeVersions: ['1.0.0']), + // We'd rather render a button instead of a dropdown + if (items.length <= 1) { + return ( + false : undefined} + /> + ); + } + return ( + false : undefined} + /> + ); +} diff --git a/docs-website/versions.json b/docs-website/versions.json new file mode 100644 index 00000000000000..a5493c26a4c659 --- /dev/null +++ b/docs-website/versions.json @@ -0,0 +1,4 @@ +[ + "0.11.0", + "0.10.5" +] diff --git a/docs-website/yarn.lock b/docs-website/yarn.lock index ccf0793ec3c762..5698029bff70a8 100644 --- a/docs-website/yarn.lock +++ b/docs-website/yarn.lock @@ -2,140 +2,148 @@ # yarn lockfile v1 -"@algolia/autocomplete-core@1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.2.tgz#8abbed88082f611997538760dffcb43b33b1fd1d" - integrity sha512-eclwUDC6qfApNnEfu1uWcL/rudQsn59tjEoUYZYE2JSXZrHLRjBUGMxiCoknobU2Pva8ejb0eRxpIYDtVVqdsw== +"@algolia/autocomplete-core@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz#1d56482a768c33aae0868c8533049e02e8961be7" + integrity sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw== dependencies: - "@algolia/autocomplete-shared" "1.7.2" + "@algolia/autocomplete-plugin-algolia-insights" "1.9.3" + "@algolia/autocomplete-shared" "1.9.3" -"@algolia/autocomplete-preset-algolia@1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.2.tgz#9cd4f64b3d64399657ee2dc2b7e0a939e0713a26" - integrity sha512-+RYEG6B0QiGGfRb2G3MtPfyrl0dALF3cQNTWBzBX6p5o01vCCGTTinAm2UKG3tfc2CnOMAtnPLkzNZyJUpnVJw== +"@algolia/autocomplete-plugin-algolia-insights@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz#9b7f8641052c8ead6d66c1623d444cbe19dde587" + integrity sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg== + dependencies: + "@algolia/autocomplete-shared" "1.9.3" + +"@algolia/autocomplete-preset-algolia@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz#64cca4a4304cfcad2cf730e83067e0c1b2f485da" + integrity sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA== dependencies: - "@algolia/autocomplete-shared" "1.7.2" + "@algolia/autocomplete-shared" "1.9.3" -"@algolia/autocomplete-shared@1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.2.tgz#daa23280e78d3b42ae9564d12470ae034db51a89" - integrity sha512-QCckjiC7xXHIUaIL3ektBtjJ0w7tTA3iqKcAE/Hjn1lZ5omp7i3Y4e09rAr9ZybqirL7AbxCLLq0Ra5DDPKeug== +"@algolia/autocomplete-shared@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz#2e22e830d36f0a9cf2c0ccd3c7f6d59435b77dfa" + integrity sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ== -"@algolia/cache-browser-local-storage@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.14.3.tgz#b9e0da012b2f124f785134a4d468ee0841b2399d" - integrity sha512-hWH1yCxgG3+R/xZIscmUrWAIBnmBFHH5j30fY/+aPkEZWt90wYILfAHIOZ1/Wxhho5SkPfwFmT7ooX2d9JeQBw== +"@algolia/cache-browser-local-storage@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.19.1.tgz#d29f42775ed4d117182897ac164519c593faf399" + integrity sha512-FYAZWcGsFTTaSAwj9Std8UML3Bu8dyWDncM7Ls8g+58UOe4XYdlgzXWbrIgjaguP63pCCbMoExKr61B+ztK3tw== dependencies: - "@algolia/cache-common" "4.14.3" + "@algolia/cache-common" "4.19.1" -"@algolia/cache-common@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.14.3.tgz#a78e9faee3dfec018eab7b0996e918e06b476ac7" - integrity sha512-oZJofOoD9FQOwiGTzyRnmzvh3ZP8WVTNPBLH5xU5JNF7drDbRT0ocVT0h/xB2rPHYzOeXRrLaQQBwRT/CKom0Q== +"@algolia/cache-common@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.19.1.tgz#faa5eeacaffd6023c2cf26e9866bdb06193f9b26" + integrity sha512-XGghi3l0qA38HiqdoUY+wvGyBsGvKZ6U3vTiMBT4hArhP3fOGLXpIINgMiiGjTe4FVlTa5a/7Zf2bwlIHfRqqg== -"@algolia/cache-in-memory@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.14.3.tgz#96cefb942aeb80e51e6a7e29f25f4f7f3439b736" - integrity sha512-ES0hHQnzWjeioLQf5Nq+x1AWdZJ50znNPSH3puB/Y4Xsg4Av1bvLmTJe7SY2uqONaeMTvL0OaVcoVtQgJVw0vg== +"@algolia/cache-in-memory@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.19.1.tgz#afe4f0f21149800358379871089e0141fb72415b" + integrity sha512-+PDWL+XALGvIginigzu8oU6eWw+o76Z8zHbBovWYcrtWOEtinbl7a7UTt3x3lthv+wNuFr/YD1Gf+B+A9V8n5w== dependencies: - "@algolia/cache-common" "4.14.3" + "@algolia/cache-common" "4.19.1" -"@algolia/client-account@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.14.3.tgz#6d7d032a65c600339ce066505c77013d9a9e4966" - integrity sha512-PBcPb0+f5Xbh5UfLZNx2Ow589OdP8WYjB4CnvupfYBrl9JyC1sdH4jcq/ri8osO/mCZYjZrQsKAPIqW/gQmizQ== +"@algolia/client-account@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.19.1.tgz#1fa65881baab79ad35af6bcf44646a13b8d5edc9" + integrity sha512-Oy0ritA2k7AMxQ2JwNpfaEcgXEDgeyKu0V7E7xt/ZJRdXfEpZcwp9TOg4TJHC7Ia62gIeT2Y/ynzsxccPw92GA== dependencies: - "@algolia/client-common" "4.14.3" - "@algolia/client-search" "4.14.3" - "@algolia/transporter" "4.14.3" + "@algolia/client-common" "4.19.1" + "@algolia/client-search" "4.19.1" + "@algolia/transporter" "4.19.1" -"@algolia/client-analytics@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.14.3.tgz#ca409d00a8fff98fdcc215dc96731039900055dc" - integrity sha512-eAwQq0Hb/aauv9NhCH5Dp3Nm29oFx28sayFN2fdOWemwSeJHIl7TmcsxVlRsO50fsD8CtPcDhtGeD3AIFLNvqw== +"@algolia/client-analytics@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.19.1.tgz#e6ed79acd4de5a0284c9696bf4e1c25278ba34db" + integrity sha512-5QCq2zmgdZLIQhHqwl55ZvKVpLM3DNWjFI4T+bHr3rGu23ew2bLO4YtyxaZeChmDb85jUdPDouDlCumGfk6wOg== dependencies: - "@algolia/client-common" "4.14.3" - "@algolia/client-search" "4.14.3" - "@algolia/requester-common" "4.14.3" - "@algolia/transporter" "4.14.3" + "@algolia/client-common" "4.19.1" + "@algolia/client-search" "4.19.1" + "@algolia/requester-common" "4.19.1" + "@algolia/transporter" "4.19.1" -"@algolia/client-common@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.14.3.tgz#c44e48652b2121a20d7a40cfd68d095ebb4191a8" - integrity sha512-jkPPDZdi63IK64Yg4WccdCsAP4pHxSkr4usplkUZM5C1l1oEpZXsy2c579LQ0rvwCs5JFmwfNG4ahOszidfWPw== +"@algolia/client-common@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.19.1.tgz#40a8387316fa61d62ad1091beb3a8e227f008e75" + integrity sha512-3kAIVqTcPrjfS389KQvKzliC559x+BDRxtWamVJt8IVp7LGnjq+aVAXg4Xogkur1MUrScTZ59/AaUd5EdpyXgA== dependencies: - "@algolia/requester-common" "4.14.3" - "@algolia/transporter" "4.14.3" + "@algolia/requester-common" "4.19.1" + "@algolia/transporter" "4.19.1" -"@algolia/client-personalization@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.14.3.tgz#8f71325035aa2a5fa7d1d567575235cf1d6c654f" - integrity sha512-UCX1MtkVNgaOL9f0e22x6tC9e2H3unZQlSUdnVaSKpZ+hdSChXGaRjp2UIT7pxmPqNCyv51F597KEX5WT60jNg== +"@algolia/client-personalization@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.19.1.tgz#fe362e0684dc74c3504c3641c5a7488c6ae02e07" + integrity sha512-8CWz4/H5FA+krm9HMw2HUQenizC/DxUtsI5oYC0Jxxyce1vsr8cb1aEiSJArQT6IzMynrERif1RVWLac1m36xw== dependencies: - "@algolia/client-common" "4.14.3" - "@algolia/requester-common" "4.14.3" - "@algolia/transporter" "4.14.3" + "@algolia/client-common" "4.19.1" + "@algolia/requester-common" "4.19.1" + "@algolia/transporter" "4.19.1" -"@algolia/client-search@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.14.3.tgz#cf1e77549f5c3e73408ffe6441ede985fde69da0" - integrity sha512-I2U7xBx5OPFdPLA8AXKUPPxGY3HDxZ4r7+mlZ8ZpLbI8/ri6fnu6B4z3wcL7sgHhDYMwnAE8Xr0AB0h3Hnkp4A== +"@algolia/client-search@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.19.1.tgz#5e54601aa5f5cea790cec3f2cde4af9d6403871e" + integrity sha512-mBecfMFS4N+yK/p0ZbK53vrZbL6OtWMk8YmnOv1i0LXx4pelY8TFhqKoTit3NPVPwoSNN0vdSN9dTu1xr1XOVw== dependencies: - "@algolia/client-common" "4.14.3" - "@algolia/requester-common" "4.14.3" - "@algolia/transporter" "4.14.3" + "@algolia/client-common" "4.19.1" + "@algolia/requester-common" "4.19.1" + "@algolia/transporter" "4.19.1" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/logger-common@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.14.3.tgz#87d4725e7f56ea5a39b605771b7149fff62032a7" - integrity sha512-kUEAZaBt/J3RjYi8MEBT2QEexJR2kAE2mtLmezsmqMQZTV502TkHCxYzTwY2dE7OKcUTxi4OFlMuS4GId9CWPw== +"@algolia/logger-common@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.19.1.tgz#0e46a11510f3e94e1afc0ac780ae52e9597be78f" + integrity sha512-i6pLPZW/+/YXKis8gpmSiNk1lOmYCmRI6+x6d2Qk1OdfvX051nRVdalRbEcVTpSQX6FQAoyeaui0cUfLYW5Elw== -"@algolia/logger-console@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.14.3.tgz#1f19f8f0a5ef11f01d1f9545290eb6a89b71fb8a" - integrity sha512-ZWqAlUITktiMN2EiFpQIFCJS10N96A++yrexqC2Z+3hgF/JcKrOxOdT4nSCQoEPvU4Ki9QKbpzbebRDemZt/hw== +"@algolia/logger-console@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.19.1.tgz#656a6f4ebb5de39af6ef7095c398d9ab3cceb87d" + integrity sha512-jj72k9GKb9W0c7TyC3cuZtTr0CngLBLmc8trzZlXdfvQiigpUdvTi1KoWIb2ZMcRBG7Tl8hSb81zEY3zI2RlXg== dependencies: - "@algolia/logger-common" "4.14.3" + "@algolia/logger-common" "4.19.1" -"@algolia/requester-browser-xhr@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.14.3.tgz#bcf55cba20f58fd9bc95ee55793b5219f3ce8888" - integrity sha512-AZeg2T08WLUPvDncl2XLX2O67W5wIO8MNaT7z5ii5LgBTuk/rU4CikTjCe2xsUleIZeFl++QrPAi4Bdxws6r/Q== +"@algolia/requester-browser-xhr@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.19.1.tgz#7341ea2f980b8980a2976110142026721e452187" + integrity sha512-09K/+t7lptsweRTueHnSnmPqIxbHMowejAkn9XIcJMLdseS3zl8ObnS5GWea86mu3vy4+8H+ZBKkUN82Zsq/zg== dependencies: - "@algolia/requester-common" "4.14.3" + "@algolia/requester-common" "4.19.1" -"@algolia/requester-common@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.14.3.tgz#2d02fbe01afb7ae5651ae8dfe62d6c089f103714" - integrity sha512-RrRzqNyKFDP7IkTuV3XvYGF9cDPn9h6qEDl595lXva3YUk9YSS8+MGZnnkOMHvjkrSCKfoLeLbm/T4tmoIeclw== +"@algolia/requester-common@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.19.1.tgz#f3396c77631b9d36e8d4d6f819a2c27f9ddbf7a1" + integrity sha512-BisRkcWVxrDzF1YPhAckmi2CFYK+jdMT60q10d7z3PX+w6fPPukxHRnZwooiTUrzFe50UBmLItGizWHP5bDzVQ== -"@algolia/requester-node-http@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.14.3.tgz#72389e1c2e5d964702451e75e368eefe85a09d8f" - integrity sha512-O5wnPxtDRPuW2U0EaOz9rMMWdlhwP0J0eSL1Z7TtXF8xnUeeUyNJrdhV5uy2CAp6RbhM1VuC3sOJcIR6Av+vbA== +"@algolia/requester-node-http@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.19.1.tgz#ea210de9642628b3bdda1dd7fcd1fcb686da442e" + integrity sha512-6DK52DHviBHTG2BK/Vv2GIlEw7i+vxm7ypZW0Z7vybGCNDeWzADx+/TmxjkES2h15+FZOqVf/Ja677gePsVItA== dependencies: - "@algolia/requester-common" "4.14.3" + "@algolia/requester-common" "4.19.1" -"@algolia/transporter@4.14.3": - version "4.14.3" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.14.3.tgz#5593036bd9cf2adfd077fdc3e81d2e6118660a7a" - integrity sha512-2qlKlKsnGJ008exFRb5RTeTOqhLZj0bkMCMVskxoqWejs2Q2QtWmsiH98hDfpw0fmnyhzHEt0Z7lqxBYp8bW2w== +"@algolia/transporter@4.19.1": + version "4.19.1" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.19.1.tgz#b5787299740c4bec9ba05502d98c14b5999860c8" + integrity sha512-nkpvPWbpuzxo1flEYqNIbGz7xhfhGOKGAZS7tzC+TELgEmi7z99qRyTfNSUlW7LZmB3ACdnqAo+9A9KFBENviQ== dependencies: - "@algolia/cache-common" "4.14.3" - "@algolia/logger-common" "4.14.3" - "@algolia/requester-common" "4.14.3" + "@algolia/cache-common" "4.19.1" + "@algolia/logger-common" "4.19.1" + "@algolia/requester-common" "4.19.1" -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== dependencies: - "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" "@ant-design/colors@^6.0.0": @@ -145,46 +153,65 @@ dependencies: "@ctrl/tinycolor" "^3.4.0" -"@ant-design/cssinjs@^1.0.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.2.0.tgz#3ba7d79617e0aa617823d7ba3f5d30072a8ab870" - integrity sha512-TjZVH4lgc7jAhYn9yStjnQI7u93b+VAg2oXIyzy12XjnFjCTR+nQIHfuixK+Vm0sx2L8ecDOBDEPT9ldCA7RPQ== +"@ant-design/colors@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@ant-design/colors/-/colors-7.0.0.tgz#eb7eecead124c3533aea05d61254f0a17f2b61b3" + integrity sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg== + dependencies: + "@ctrl/tinycolor" "^3.4.0" + +"@ant-design/cssinjs@^1.16.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.17.0.tgz#a3f69cf5131539b76ccdbfced43d242557599fea" + integrity sha512-MgGCZ6sfD3yQB0XW0hN4jgixMxApTlDYyct+pc7fRZNO4CaqWWm/9iXkkljNR27lyWLZmm+XiDfcIOo1bnrnMA== dependencies: "@babel/runtime" "^7.11.1" "@emotion/hash" "^0.8.0" "@emotion/unitless" "^0.7.5" classnames "^2.3.1" csstype "^3.0.10" - rc-util "^5.24.2" - shallowequal "^1.1.0" + rc-util "^5.35.0" stylis "^4.0.13" -"@ant-design/icons-svg@^4.2.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz#8630da8eb4471a4aabdaed7d1ff6a97dcb2cf05a" - integrity sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw== +"@ant-design/icons-svg@^4.3.0": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@ant-design/icons-svg/-/icons-svg-4.3.1.tgz#4b2f65a17d4d32b526baa6414aca2117382bf8da" + integrity sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g== "@ant-design/icons@^4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-4.7.0.tgz#8c3cbe0a556ba92af5dc7d1e70c0b25b5179af0f" - integrity sha512-aoB4Z7JA431rt6d4u+8xcNPPCrdufSRMUOpxa1ab6mz1JCQZOEVolj2WVs/tDFmN62zzK30mNelEsprLYsSF3g== + version "4.8.1" + resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-4.8.1.tgz#44f6c81f609811d68d48a123eb5dcc477f8fbcb7" + integrity sha512-JRAuiqllnMsiZIO8OvBOeFconprC3cnMpJ9MvXrHh+H5co9rlg8/aSHQfLf5jKKe18lUgRaIwC2pz8YxH9VuCA== dependencies: "@ant-design/colors" "^6.0.0" - "@ant-design/icons-svg" "^4.2.1" + "@ant-design/icons-svg" "^4.3.0" "@babel/runtime" "^7.11.2" classnames "^2.2.6" + lodash "^4.17.15" rc-util "^5.9.4" -"@ant-design/react-slick@~0.29.1": - version "0.29.2" - resolved "https://registry.yarnpkg.com/@ant-design/react-slick/-/react-slick-0.29.2.tgz#53e6a7920ea3562eebb304c15a7fc2d7e619d29c" - integrity sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA== +"@ant-design/icons@^5.2.2": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.2.5.tgz#852474359e271a36e54a4ac115065fae7396277e" + integrity sha512-9Jc59v5fl5dzmxqLWtRev3dJwU7Ya9ZheoI6XmZjZiQ7PRtk77rC+Rbt7GJzAPPg43RQ4YO53RE1u8n+Et97vQ== + dependencies: + "@ant-design/colors" "^7.0.0" + "@ant-design/icons-svg" "^4.3.0" + "@babel/runtime" "^7.11.2" + classnames "^2.2.6" + lodash.camelcase "^4.3.0" + rc-util "^5.31.1" + +"@ant-design/react-slick@~1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@ant-design/react-slick/-/react-slick-1.0.2.tgz#241bb412aeacf7ff5d50c61fa5db66773fde6b56" + integrity sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ== dependencies: "@babel/runtime" "^7.10.4" classnames "^2.2.5" json2mq "^0.2.0" - lodash "^4.17.21" resize-observer-polyfill "^1.5.1" + throttle-debounce "^5.0.0" "@ardatan/aggregate-error@0.0.6": version "0.0.6" @@ -193,17 +220,18 @@ dependencies: tslib "~2.0.1" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.10", "@babel/code-frame@^7.22.5", "@babel/code-frame@^7.8.3": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5": - version "7.20.10" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec" - integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" + integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== "@babel/core@7.12.9": version "7.12.9" @@ -227,369 +255,260 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.18.6": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.13.tgz#9be8c44512751b05094a4d3ab05fc53a47ce00ac" - integrity sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.18.13" - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-module-transforms" "^7.18.9" - "@babel/helpers" "^7.18.9" - "@babel/parser" "^7.18.13" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.18.13" - "@babel/types" "^7.18.13" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/core@^7.19.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.7.tgz#37072f951bd4d28315445f66e0ec9f6ae0c8c35f" - integrity sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.20.7" - "@babel/helpers" "^7.20.7" - "@babel/parser" "^7.20.7" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" +"@babel/core@^7.18.6", "@babel/core@^7.19.6": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.11.tgz#8033acaa2aa24c3f814edaaa057f3ce0ba559c24" + integrity sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.10" + "@babel/generator" "^7.22.10" + "@babel/helper-compilation-targets" "^7.22.10" + "@babel/helper-module-transforms" "^7.22.9" + "@babel/helpers" "^7.22.11" + "@babel/parser" "^7.22.11" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.11" + "@babel/types" "^7.22.11" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" + json5 "^2.2.3" + semver "^6.3.1" -"@babel/generator@^7.12.5", "@babel/generator@^7.18.13", "@babel/generator@^7.18.7", "@babel/generator@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" - integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== +"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.10.tgz#c92254361f398e160645ac58831069707382b722" + integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.22.10" "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" - integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.5": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz#573e735937e99ea75ea30788b57eb52fab7468c9" + integrity sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ== dependencies: - "@babel/helper-explode-assignable-expression" "^7.18.6" - "@babel/types" "^7.18.9" + "@babel/types" "^7.22.10" -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0", "@babel/helper-compilation-targets@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" - integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== +"@babel/helper-compilation-targets@^7.22.10", "@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz#01d648bbc25dd88f513d862ee0df27b7d4e67024" + integrity sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q== dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.5" + browserslist "^4.21.9" lru-cache "^5.1.1" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5", "@babel/helper-create-class-features-plugin@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.7.tgz#d0e1f8d7e4ed5dac0389364d9c0c191d948ade6f" - integrity sha512-LtoWbDXOaidEf50hmdDqn9g8VEzsorMexoWMQdQODbvmqYmaF23pBP5VNPAGIFHsFQCIeKokDiz3CH5Y2jlY6w== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-member-expression-to-functions" "^7.20.7" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-split-export-declaration" "^7.18.6" - -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca" - integrity sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - regexpu-core "^5.2.1" - -"@babel/helper-define-polyfill-provider@^0.3.2", "@babel/helper-define-polyfill-provider@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" - integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== - dependencies: - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.5": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.11.tgz#4078686740459eeb4af3494a273ac09148dfb213" + integrity sha512-y1grdYL4WzmUDBRGK0pDbIoFd7UZKoDurDzWEoNMYoj1EL+foGRQNyPWDcC+YyegN5y1DUsFFmzjGijB3nSVAQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz#9d8e61a8d9366fe66198f57c40565663de0825f6" + integrity sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz#82c825cadeeeee7aad237618ebbe8fa1710015d7" + integrity sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" - semver "^6.1.2" -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== +"@babel/helper-environment-visitor@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" + integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== -"@babel/helper-explode-assignable-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" - integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== +"@babel/helper-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" + integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== dependencies: - "@babel/types" "^7.18.6" + "@babel/template" "^7.22.5" + "@babel/types" "^7.22.5" -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/types" "^7.22.5" -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== +"@babel/helper-member-expression-to-functions@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz#0a7c56117cad3372fbf8d2fb4bf8f8d64a1e76b2" + integrity sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" -"@babel/helper-member-expression-to-functions@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" - integrity sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw== +"@babel/helper-module-imports@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" + integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.22.5" -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.18.9", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.20.7": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" - integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.20.2" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.10" - "@babel/types" "^7.20.7" - -"@babel/helper-optimise-call-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" - integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz#92dfcb1fbbb2bc62529024f72d942a8c97142129" + integrity sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.5" + +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" -"@babel/helper-plugin-utils@7.10.4", "@babel/helper-plugin-utils@^7.10.4": +"@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" - integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== - -"@babel/helper-remap-async-to-generator@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" - integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-wrap-function" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" - integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-member-expression-to-functions" "^7.20.7" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/helper-simple-access@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" - integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== - dependencies: - "@babel/types" "^7.20.2" - -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" - integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== - dependencies: - "@babel/types" "^7.20.0" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helper-wrap-function@^7.18.9": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" - integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q== - dependencies: - "@babel/helper-function-name" "^7.19.0" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.5" - "@babel/types" "^7.20.5" - -"@babel/helpers@^7.12.5", "@babel/helpers@^7.18.9", "@babel/helpers@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" - integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== - dependencies: - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-remap-async-to-generator@^7.22.5", "@babel/helper-remap-async-to-generator@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz#53a25b7484e722d7efb9c350c75c032d4628de82" + integrity sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-wrap-function" "^7.22.9" + +"@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz#cbdc27d6d8d18cd22c81ae4293765a5d9afd0779" + integrity sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + +"@babel/helper-validator-option@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" + integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== + +"@babel/helper-wrap-function@^7.22.9": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz#d845e043880ed0b8c18bd194a12005cb16d2f614" + integrity sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ== + dependencies: + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/types" "^7.22.10" + +"@babel/helpers@^7.12.5", "@babel/helpers@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.11.tgz#b02f5d5f2d7abc21ab59eeed80de410ba70b056a" + integrity sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg== + dependencies: + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.11" + "@babel/types" "^7.22.11" + +"@babel/highlight@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16" + integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.18.13", "@babel/parser@^7.18.8", "@babel/parser@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" - integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" - integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz#d9c85589258539a22a901033853101a6198d4ef1" - integrity sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.7" - -"@babel/plugin-proposal-async-generator-functions@^7.20.1": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" - integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-class-static-block@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz#92592e9029b13b15be0f7ce6a7aedc2879ca45a7" - integrity sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-dynamic-import@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" - integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" - integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" - integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz#dfbcaa8f7b4d37b51e8bfb46d94a5aea2bb89d83" - integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" +"@babel/parser@^7.12.7", "@babel/parser@^7.18.8", "@babel/parser@^7.22.11", "@babel/parser@^7.22.5": + version "7.22.14" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.14.tgz#c7de58e8de106e88efca42ce17f0033209dfd245" + integrity sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ== -"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" + integrity sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-proposal-numeric-separator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz#fef09f9499b1f1c930da8a0c419db42167d792ca" + integrity sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.22.5" "@babel/plugin-proposal-object-rest-spread@7.12.1": version "7.12.1" @@ -600,59 +519,10 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-object-rest-spread@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" - integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== - dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.20.7" - -"@babel/plugin-proposal-optional-catch-binding@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.18.9", "@babel/plugin-proposal-optional-chaining@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz#49f2b372519ab31728cc14115bb0998b15bfda55" - integrity sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-methods@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" - integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-private-property-in-object@^7.18.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135" - integrity sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.20.5" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" - integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -689,12 +559,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-import-assertions@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" - integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== +"@babel/plugin-syntax-import-assertions@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz#07d252e2aa0bc6125567f742cd58619cb14dce98" + integrity sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-attributes@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz#ab840248d834410b829f569f5262b9e517555ecb" + integrity sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" @@ -710,12 +594,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== +"@babel/plugin-syntax-jsx@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" + integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -773,357 +657,491 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" - integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== +"@babel/plugin-syntax-typescript@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272" + integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-arrow-functions@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz#bea332b0e8b2dab3dafe55a163d8227531ab0551" - integrity sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ== +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-async-to-generator@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz#dfee18623c8cb31deb796aa3ca84dda9cea94354" - integrity sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q== +"@babel/plugin-transform-arrow-functions@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz#e5ba566d0c58a5b2ba2a8b795450641950b71958" + integrity sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw== dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-block-scoped-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" - integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== +"@babel/plugin-transform-async-generator-functions@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.11.tgz#dbe3b1ff5a52e2e5edc4b19a60d325a675ed2649" + integrity sha512-0pAlmeRJn6wU84zzZsEOx1JV1Jf8fqO9ok7wofIJwUnplYo247dcd24P+cMJht7ts9xkzdtB0EPHmOb7F+KzXw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-transform-async-to-generator@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz#c7a85f44e46f8952f6d27fe57c2ed3cc084c3775" + integrity sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ== + dependencies: + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.5" + +"@babel/plugin-transform-block-scoped-functions@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz#27978075bfaeb9fa586d3cb63a3d30c1de580024" + integrity sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-block-scoping@^7.20.2": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.11.tgz#9f5a3424bd112a3f32fe0cf9364fbb155cff262a" - integrity sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - -"@babel/plugin-transform-classes@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz#f438216f094f6bb31dc266ebfab8ff05aecad073" - integrity sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-split-export-declaration" "^7.18.6" +"@babel/plugin-transform-block-scoping@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz#88a1dccc3383899eb5e660534a76a22ecee64faa" + integrity sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz#97a56e31ad8c9dc06a0b3710ce7803d5a48cca77" + integrity sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-static-block@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz#dc8cc6e498f55692ac6b4b89e56d87cec766c974" + integrity sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz#e04d7d804ed5b8501311293d1a0e6d43e94c3363" + integrity sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.18.9": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz#704cc2fd155d1c996551db8276d55b9d46e4d0aa" - integrity sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ== +"@babel/plugin-transform-computed-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz#cd1e994bf9f316bd1c2dafcd02063ec261bb3869" + integrity sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/template" "^7.20.7" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.5" -"@babel/plugin-transform-destructuring@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz#8bda578f71620c7de7c93af590154ba331415454" - integrity sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA== +"@babel/plugin-transform-destructuring@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz#38e2273814a58c810b6c34ea293be4973c4eb5e2" + integrity sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" - integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== +"@babel/plugin-transform-dotall-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz#dbb4f0e45766eb544e193fb00e65a1dd3b2a4165" + integrity sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-duplicate-keys@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" - integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== +"@babel/plugin-transform-duplicate-keys@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz#b6e6428d9416f5f0bba19c70d1e6e7e0b88ab285" + integrity sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-exponentiation-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" - integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== +"@babel/plugin-transform-dynamic-import@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz#2c7722d2a5c01839eaf31518c6ff96d408e447aa" + integrity sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-for-of@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" - integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== +"@babel/plugin-transform-exponentiation-operator@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz#402432ad544a1f9a480da865fda26be653e48f6a" + integrity sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" - integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== +"@babel/plugin-transform-export-namespace-from@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz#b3c84c8f19880b6c7440108f8929caf6056db26c" + integrity sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw== dependencies: - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" - integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== +"@babel/plugin-transform-for-of@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz#ab1b8a200a8f990137aff9a084f8de4099ab173f" + integrity sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-member-expression-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" - integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== +"@babel/plugin-transform-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz#935189af68b01898e0d6d99658db6b164205c143" + integrity sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-compilation-targets" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-modules-amd@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz#3daccca8e4cc309f03c3a0c4b41dc4b26f55214a" - integrity sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g== +"@babel/plugin-transform-json-strings@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz#689a34e1eed1928a40954e37f74509f48af67835" + integrity sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw== dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-modules-commonjs@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz#8cb23010869bf7669fd4b3098598b6b2be6dc607" - integrity sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw== +"@babel/plugin-transform-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz#e9341f4b5a167952576e23db8d435849b1dd7920" + integrity sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g== dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-modules-systemjs@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz#467ec6bba6b6a50634eea61c9c232654d8a4696e" - integrity sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw== +"@babel/plugin-transform-logical-assignment-operators@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz#24c522a61688bde045b7d9bc3c2597a4d948fc9c" + integrity sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ== dependencies: - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-modules-umd@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" - integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== +"@babel/plugin-transform-member-expression-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz#4fcc9050eded981a468347dd374539ed3e058def" + integrity sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew== dependencies: - "@babel/helper-module-transforms" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8" - integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA== +"@babel/plugin-transform-modules-amd@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz#4e045f55dcf98afd00f85691a68fc0780704f526" + integrity sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.20.5" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-module-transforms" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-new-target@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" - integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== +"@babel/plugin-transform-modules-commonjs@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.11.tgz#d7991d3abad199c03b68ee66a64f216c47ffdfae" + integrity sha512-o2+bg7GDS60cJMgz9jWqRUsWkMzLCxp+jFDeDUT5sjRlAxcJWZ2ylNdI7QQ2+CH5hWu7OnN+Cv3htt7AkSf96g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-module-transforms" "^7.22.9" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" -"@babel/plugin-transform-object-super@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" - integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== +"@babel/plugin-transform-modules-systemjs@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz#3386be5875d316493b517207e8f1931d93154bb1" + integrity sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.22.9" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.1", "@babel/plugin-transform-parameters@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz#0ee349e9d1bc96e78e3b37a7af423a4078a7083f" - integrity sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA== +"@babel/plugin-transform-modules-umd@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz#4694ae40a87b1745e3775b6a7fe96400315d4f98" + integrity sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-module-transforms" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-property-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" - integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" + integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-new-target@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz#1b248acea54ce44ea06dfd37247ba089fcf9758d" + integrity sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz#debef6c8ba795f5ac67cd861a81b744c5d38d9fc" + integrity sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz#498d77dc45a6c6db74bb829c02a01c1d719cbfbd" + integrity sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.11.tgz#dbbb06ce783cd994a8f430d8cefa553e9b42ca62" + integrity sha512-nX8cPFa6+UmbepISvlf5jhQyaC7ASs/7UxHmMkuJ/k5xSHvDPPaibMo+v3TXwU/Pjqhep/nFNpd3zn4YR59pnw== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.10" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.22.5" + +"@babel/plugin-transform-object-super@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz#794a8d2fcb5d0835af722173c1a9d704f44e218c" + integrity sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.5" + +"@babel/plugin-transform-optional-catch-binding@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz#461cc4f578a127bb055527b3e77404cad38c08e0" + integrity sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.22.12", "@babel/plugin-transform-optional-chaining@^7.22.5": + version "7.22.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.12.tgz#d7ebf6a88cd2f4d307b0e000ab630acd8124b333" + integrity sha512-7XXCVqZtyFWqjDsYDY4T45w4mlx1rf7aOgkc/Ww76xkgBiOlmjPkx36PBLHa1k1rwWvVgYMPsbuVnIamx2ZQJw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz#c3542dd3c39b42c8069936e48717a8d179d63a18" + integrity sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-methods@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz#21c8af791f76674420a147ae62e9935d790f8722" + integrity sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-property-in-object@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz#ad45c4fc440e9cb84c718ed0906d96cf40f9a4e1" + integrity sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz#b5ddabd73a4f7f26cd0e20f5db48290b88732766" + integrity sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-react-constant-elements@^7.18.12": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.20.2.tgz#3f02c784e0b711970d7d8ccc96c4359d64e27ac7" - integrity sha512-KS/G8YI8uwMGKErLFOHS/ekhqdHhpEloxs43NecQHVgo2QuQSyJhGIY1fL8UGl9wy5ItVwwoUL4YxVqsplGq2g== + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz#6dfa7c1c37f7d7279e417ceddf5a04abb8bb9c29" + integrity sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-react-display-name@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" - integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== +"@babel/plugin-transform-react-display-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz#3c4326f9fce31c7968d6cb9debcaf32d9e279a2b" + integrity sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-react-jsx-development@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" - integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== +"@babel/plugin-transform-react-jsx-development@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87" + integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A== dependencies: - "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.22.5" -"@babel/plugin-transform-react-jsx@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.20.7.tgz#025d85a1935fd7e19dfdcb1b1d4df34d4da484f7" - integrity sha512-Tfq7qqD+tRj3EoDhY00nn2uP2hsRxgYGi5mLQ5TimKav0a9Lrpd4deE+fcLXU8zFYRjlKPHZhpCvfEA6qnBxqQ== +"@babel/plugin-transform-react-jsx@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz#932c291eb6dd1153359e2a90cb5e557dcf068416" + integrity sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-jsx" "^7.18.6" - "@babel/types" "^7.20.7" + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/types" "^7.22.5" -"@babel/plugin-transform-react-pure-annotations@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" - integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== +"@babel/plugin-transform-react-pure-annotations@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz#1f58363eef6626d6fa517b95ac66fe94685e32c0" + integrity sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-regenerator@^7.18.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d" - integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ== +"@babel/plugin-transform-regenerator@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz#8ceef3bd7375c4db7652878b0241b2be5d0c3cca" + integrity sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - regenerator-transform "^0.15.1" + "@babel/helper-plugin-utils" "^7.22.5" + regenerator-transform "^0.15.2" -"@babel/plugin-transform-reserved-words@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" - integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== +"@babel/plugin-transform-reserved-words@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz#832cd35b81c287c4bcd09ce03e22199641f964fb" + integrity sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-runtime@^7.18.6": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz#37d14d1fa810a368fd635d4d1476c0154144a96f" - integrity sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ== - dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.9" - babel-plugin-polyfill-corejs2 "^0.3.2" - babel-plugin-polyfill-corejs3 "^0.5.3" - babel-plugin-polyfill-regenerator "^0.4.0" - semver "^6.3.0" + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.10.tgz#89eda6daf1d3af6f36fb368766553054c8d7cd46" + integrity sha512-RchI7HePu1eu0CYNKHHHQdfenZcM4nz8rew5B1VWqeRKdcwW5aQ5HeG9eTUbWiAS1UrmHVLmoxTWHt3iLD/NhA== + dependencies: + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + babel-plugin-polyfill-corejs2 "^0.4.5" + babel-plugin-polyfill-corejs3 "^0.8.3" + babel-plugin-polyfill-regenerator "^0.5.2" + semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" - integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== +"@babel/plugin-transform-shorthand-properties@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz#6e277654be82b5559fc4b9f58088507c24f0c624" + integrity sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-spread@^7.19.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz#c2d83e0b99d3bf83e07b11995ee24bf7ca09401e" - integrity sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw== +"@babel/plugin-transform-spread@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz#6487fd29f229c95e284ba6c98d65eafb893fea6b" + integrity sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" -"@babel/plugin-transform-sticky-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" - integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== +"@babel/plugin-transform-sticky-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz#295aba1595bfc8197abd02eae5fc288c0deb26aa" + integrity sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-template-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" - integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== +"@babel/plugin-transform-template-literals@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz#8f38cf291e5f7a8e60e9f733193f0bcc10909bff" + integrity sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-typeof-symbol@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" - integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== +"@babel/plugin-transform-typeof-symbol@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz#5e2ba478da4b603af8673ff7c54f75a97b716b34" + integrity sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-typescript@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.7.tgz#673f49499cd810ae32a1ea5f3f8fab370987e055" - integrity sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw== +"@babel/plugin-transform-typescript@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.11.tgz#9f27fb5e51585729374bb767ab6a6d9005a23329" + integrity sha512-0E4/L+7gfvHub7wsbTv03oRtD69X31LByy44fGmFzbZScpupFByMcgCJ0VbBTkzyjSJKuRoGN8tcijOWKTmqOA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-typescript" "^7.20.0" + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.11" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-typescript" "^7.22.5" -"@babel/plugin-transform-unicode-escapes@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" - integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== +"@babel/plugin-transform-unicode-escapes@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz#c723f380f40a2b2f57a62df24c9005834c8616d9" + integrity sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-unicode-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" - integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== +"@babel/plugin-transform-unicode-property-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz#098898f74d5c1e86660dc112057b2d11227f1c81" + integrity sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz#ce7e7bb3ef208c4ff67e02a22816656256d7a183" + integrity sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-sets-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz#77788060e511b708ffc7d42fdfbc5b37c3004e91" + integrity sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/preset-env@^7.18.6", "@babel/preset-env@^7.19.4": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" - integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== - dependencies: - "@babel/compat-data" "^7.20.1" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-async-generator-functions" "^7.20.1" - "@babel/plugin-proposal-class-properties" "^7.18.6" - "@babel/plugin-proposal-class-static-block" "^7.18.6" - "@babel/plugin-proposal-dynamic-import" "^7.18.6" - "@babel/plugin-proposal-export-namespace-from" "^7.18.9" - "@babel/plugin-proposal-json-strings" "^7.18.6" - "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" - "@babel/plugin-proposal-numeric-separator" "^7.18.6" - "@babel/plugin-proposal-object-rest-spread" "^7.20.2" - "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-private-methods" "^7.18.6" - "@babel/plugin-proposal-private-property-in-object" "^7.18.6" - "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" + version "7.22.14" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.14.tgz#1cbb468d899f64fa71c53446f13b7ff8c0005cc1" + integrity sha512-daodMIoVo+ol/g+//c/AH+szBkFj4STQUikvBijRGL72Ph+w+AMTSh55DUETe8KJlPlDT1k/mp7NBfOuiWmoig== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.10" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.5" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.22.5" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.20.0" + "@babel/plugin-syntax-import-assertions" "^7.22.5" + "@babel/plugin-syntax-import-attributes" "^7.22.5" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -1133,139 +1151,147 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.18.6" - "@babel/plugin-transform-async-to-generator" "^7.18.6" - "@babel/plugin-transform-block-scoped-functions" "^7.18.6" - "@babel/plugin-transform-block-scoping" "^7.20.2" - "@babel/plugin-transform-classes" "^7.20.2" - "@babel/plugin-transform-computed-properties" "^7.18.9" - "@babel/plugin-transform-destructuring" "^7.20.2" - "@babel/plugin-transform-dotall-regex" "^7.18.6" - "@babel/plugin-transform-duplicate-keys" "^7.18.9" - "@babel/plugin-transform-exponentiation-operator" "^7.18.6" - "@babel/plugin-transform-for-of" "^7.18.8" - "@babel/plugin-transform-function-name" "^7.18.9" - "@babel/plugin-transform-literals" "^7.18.9" - "@babel/plugin-transform-member-expression-literals" "^7.18.6" - "@babel/plugin-transform-modules-amd" "^7.19.6" - "@babel/plugin-transform-modules-commonjs" "^7.19.6" - "@babel/plugin-transform-modules-systemjs" "^7.19.6" - "@babel/plugin-transform-modules-umd" "^7.18.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" - "@babel/plugin-transform-new-target" "^7.18.6" - "@babel/plugin-transform-object-super" "^7.18.6" - "@babel/plugin-transform-parameters" "^7.20.1" - "@babel/plugin-transform-property-literals" "^7.18.6" - "@babel/plugin-transform-regenerator" "^7.18.6" - "@babel/plugin-transform-reserved-words" "^7.18.6" - "@babel/plugin-transform-shorthand-properties" "^7.18.6" - "@babel/plugin-transform-spread" "^7.19.0" - "@babel/plugin-transform-sticky-regex" "^7.18.6" - "@babel/plugin-transform-template-literals" "^7.18.9" - "@babel/plugin-transform-typeof-symbol" "^7.18.9" - "@babel/plugin-transform-unicode-escapes" "^7.18.10" - "@babel/plugin-transform-unicode-regex" "^7.18.6" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.20.2" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - core-js-compat "^3.25.1" - semver "^6.3.0" - -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.22.5" + "@babel/plugin-transform-async-generator-functions" "^7.22.11" + "@babel/plugin-transform-async-to-generator" "^7.22.5" + "@babel/plugin-transform-block-scoped-functions" "^7.22.5" + "@babel/plugin-transform-block-scoping" "^7.22.10" + "@babel/plugin-transform-class-properties" "^7.22.5" + "@babel/plugin-transform-class-static-block" "^7.22.11" + "@babel/plugin-transform-classes" "^7.22.6" + "@babel/plugin-transform-computed-properties" "^7.22.5" + "@babel/plugin-transform-destructuring" "^7.22.10" + "@babel/plugin-transform-dotall-regex" "^7.22.5" + "@babel/plugin-transform-duplicate-keys" "^7.22.5" + "@babel/plugin-transform-dynamic-import" "^7.22.11" + "@babel/plugin-transform-exponentiation-operator" "^7.22.5" + "@babel/plugin-transform-export-namespace-from" "^7.22.11" + "@babel/plugin-transform-for-of" "^7.22.5" + "@babel/plugin-transform-function-name" "^7.22.5" + "@babel/plugin-transform-json-strings" "^7.22.11" + "@babel/plugin-transform-literals" "^7.22.5" + "@babel/plugin-transform-logical-assignment-operators" "^7.22.11" + "@babel/plugin-transform-member-expression-literals" "^7.22.5" + "@babel/plugin-transform-modules-amd" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.22.11" + "@babel/plugin-transform-modules-systemjs" "^7.22.11" + "@babel/plugin-transform-modules-umd" "^7.22.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.22.5" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.11" + "@babel/plugin-transform-numeric-separator" "^7.22.11" + "@babel/plugin-transform-object-rest-spread" "^7.22.11" + "@babel/plugin-transform-object-super" "^7.22.5" + "@babel/plugin-transform-optional-catch-binding" "^7.22.11" + "@babel/plugin-transform-optional-chaining" "^7.22.12" + "@babel/plugin-transform-parameters" "^7.22.5" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.11" + "@babel/plugin-transform-property-literals" "^7.22.5" + "@babel/plugin-transform-regenerator" "^7.22.10" + "@babel/plugin-transform-reserved-words" "^7.22.5" + "@babel/plugin-transform-shorthand-properties" "^7.22.5" + "@babel/plugin-transform-spread" "^7.22.5" + "@babel/plugin-transform-sticky-regex" "^7.22.5" + "@babel/plugin-transform-template-literals" "^7.22.5" + "@babel/plugin-transform-typeof-symbol" "^7.22.5" + "@babel/plugin-transform-unicode-escapes" "^7.22.10" + "@babel/plugin-transform-unicode-property-regex" "^7.22.5" + "@babel/plugin-transform-unicode-regex" "^7.22.5" + "@babel/plugin-transform-unicode-sets-regex" "^7.22.5" + "@babel/preset-modules" "0.1.6-no-external-plugins" + "@babel/types" "^7.22.11" + babel-plugin-polyfill-corejs2 "^0.4.5" + babel-plugin-polyfill-corejs3 "^0.8.3" + babel-plugin-polyfill-regenerator "^0.5.2" + core-js-compat "^3.31.0" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" esutils "^2.0.2" "@babel/preset-react@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" - integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.22.5.tgz#c4d6058fbf80bccad02dd8c313a9aaa67e3c3dd6" + integrity sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-transform-react-display-name" "^7.18.6" - "@babel/plugin-transform-react-jsx" "^7.18.6" - "@babel/plugin-transform-react-jsx-development" "^7.18.6" - "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.5" + "@babel/plugin-transform-react-display-name" "^7.22.5" + "@babel/plugin-transform-react-jsx" "^7.22.5" + "@babel/plugin-transform-react-jsx-development" "^7.22.5" + "@babel/plugin-transform-react-pure-annotations" "^7.22.5" "@babel/preset-typescript@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" - integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.11.tgz#f218cd0345524ac888aa3dc32f029de5b064b575" + integrity sha512-tWY5wyCZYBGY7IlalfKI1rLiGlIfnwsRHZqlky0HVv8qviwQ1Uo/05M6+s+TcTCVa6Bmoo2uJW5TMFX6Wa4qVg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-transform-typescript" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.5" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.22.11" + "@babel/plugin-transform-typescript" "^7.22.11" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== "@babel/runtime-corejs3@^7.18.6": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz#7bacecd1cb2dd694eacd32a91fcf7021c20770ae" - integrity sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A== - dependencies: - core-js-pure "^3.20.2" - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.8.4": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" - integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.20.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" - integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== - dependencies: - regenerator-runtime "^0.13.11" - -"@babel/runtime@^7.13.10": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" - integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== - dependencies: - regenerator-runtime "^0.13.11" - -"@babel/template@^7.12.7", "@babel/template@^7.18.10", "@babel/template@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" - integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.13", "@babel/traverse@^7.18.8", "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7": - version "7.20.10" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.10.tgz#2bf98239597fcec12f842756f186a9dde6d09230" - integrity sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.22.11.tgz#bf65b846cb4a03e1594dba9850c4632a992ddc04" + integrity sha512-NhfzUbdWbiE6fCFypbWCPu6AR8xre31EOPF7wwAIJEvGQ2avov04eymayWinCuyXmV1b0+jzoXP/HYzzUYdvwg== + dependencies: + core-js-pure "^3.30.2" + regenerator-runtime "^0.14.0" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.8.4": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.11.tgz#7a9ba3bbe406ad6f9e8dd4da2ece453eb23a77a4" + integrity sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.12.7", "@babel/template@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" + integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== + dependencies: + "@babel/code-frame" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/types" "^7.22.5" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.22.11": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.11.tgz#71ebb3af7a05ff97280b83f05f8865ac94b2027c" + integrity sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ== + dependencies: + "@babel/code-frame" "^7.22.10" + "@babel/generator" "^7.22.10" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.22.11" + "@babel/types" "^7.22.11" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.12.7", "@babel/types@^7.18.13", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.4.4": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" - integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== +"@babel/types@^7.12.7", "@babel/types@^7.20.0", "@babel/types@^7.22.10", "@babel/types@^7.22.11", "@babel/types@^7.22.5", "@babel/types@^7.4.4": + version "7.22.11" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.11.tgz#0e65a6a1d4d9cbaa892b2213f6159485fe632ea2" + integrity sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg== dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" "@colors/colors@1.5.0": @@ -1273,107 +1299,42 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@ctrl/tinycolor@^3.4.0": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz#75b4c27948c81e88ccd3a8902047bcd797f38d32" - integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" -"@docsearch/css@3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.3.1.tgz#32041581bffb1a834072fd21ca66d1dd9f016098" - integrity sha512-nznHXeFHpAYjyaSNFNFpU+IJPjQA7AINM8ONjDx/Zx4O/pGAvqwgmcLNc7zR8qXRutqnzLo06yN63xFn36KFBw== +"@ctrl/tinycolor@^3.4.0", "@ctrl/tinycolor@^3.6.0": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31" + integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA== + +"@discoveryjs/json-ext@0.5.7": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@docsearch/css@3.5.2": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.5.2.tgz#610f47b48814ca94041df969d9fcc47b91fc5aac" + integrity sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA== "@docsearch/react@^3.1.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.3.1.tgz#47ce4a267a9daf1b5d913b979284b4f624088003" - integrity sha512-wdeQBODPkue6yVEEg4ntt+TiGJ6iXMBUNjBQJ0s1WVoc1OdcCnks/lkQ5LEfXETYR/q9QSbCCBnMjvnSoILaag== + version "3.5.2" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.5.2.tgz#2e6bbee00eb67333b64906352734da6aef1232b9" + integrity sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng== dependencies: - "@algolia/autocomplete-core" "1.7.2" - "@algolia/autocomplete-preset-algolia" "1.7.2" - "@docsearch/css" "3.3.1" - algoliasearch "^4.0.0" + "@algolia/autocomplete-core" "1.9.3" + "@algolia/autocomplete-preset-algolia" "1.9.3" + "@docsearch/css" "3.5.2" + algoliasearch "^4.19.1" -"@docusaurus/core@2.2.0", "@docusaurus/core@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.2.0.tgz#64c9ee31502c23b93c869f8188f73afaf5fd4867" - integrity sha512-Vd6XOluKQqzG12fEs9prJgDtyn6DPok9vmUWDR2E6/nV5Fl9SVkhEQOBxwObjk3kQh7OY7vguFaLh0jqdApWsA== - dependencies: - "@babel/core" "^7.18.6" - "@babel/generator" "^7.18.7" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.18.6" - "@babel/preset-env" "^7.18.6" - "@babel/preset-react" "^7.18.6" - "@babel/preset-typescript" "^7.18.6" - "@babel/runtime" "^7.18.6" - "@babel/runtime-corejs3" "^7.18.6" - "@babel/traverse" "^7.18.8" - "@docusaurus/cssnano-preset" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" - "@slorber/static-site-generator-webpack-plugin" "^4.0.7" - "@svgr/webpack" "^6.2.1" - autoprefixer "^10.4.7" - babel-loader "^8.2.5" - babel-plugin-dynamic-import-node "^2.3.3" - boxen "^6.2.1" - chalk "^4.1.2" - chokidar "^3.5.3" - clean-css "^5.3.0" - cli-table3 "^0.6.2" - combine-promises "^1.1.0" - commander "^5.1.0" - copy-webpack-plugin "^11.0.0" - core-js "^3.23.3" - css-loader "^6.7.1" - css-minimizer-webpack-plugin "^4.0.0" - cssnano "^5.1.12" - del "^6.1.1" - detect-port "^1.3.0" - escape-html "^1.0.3" - eta "^1.12.3" - file-loader "^6.2.0" - fs-extra "^10.1.0" - html-minifier-terser "^6.1.0" - html-tags "^3.2.0" - html-webpack-plugin "^5.5.0" - import-fresh "^3.3.0" - leven "^3.1.0" - lodash "^4.17.21" - mini-css-extract-plugin "^2.6.1" - postcss "^8.4.14" - postcss-loader "^7.0.0" - prompts "^2.4.2" - react-dev-utils "^12.0.1" - react-helmet-async "^1.3.0" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.3.3" - react-router-config "^5.1.1" - react-router-dom "^5.3.3" - rtl-detect "^1.0.4" - semver "^7.3.7" - serve-handler "^6.1.3" - shelljs "^0.8.5" - terser-webpack-plugin "^5.3.3" - tslib "^2.4.0" - update-notifier "^5.1.0" - url-loader "^4.1.1" - wait-on "^6.0.1" - webpack "^5.73.0" - webpack-bundle-analyzer "^4.5.0" - webpack-dev-server "^4.9.3" - webpack-merge "^5.8.0" - webpackbar "^5.0.2" - -"@docusaurus/core@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.3.1.tgz#32849f2ffd2f086a4e55739af8c4195c5eb386f2" - integrity sha512-0Jd4jtizqnRAr7svWaBbbrCCN8mzBNd2xFLoT/IM7bGfFie5y58oz97KzXliwiLY3zWjqMXjQcuP1a5VgCv2JA== +"@docusaurus/core@2.4.1", "@docusaurus/core@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.4.1.tgz#4b8ff5766131ce3fbccaad0b1daf2ad4dc76f62d" + integrity sha512-SNsY7PshK3Ri7vtsLXVeAJGS50nJN3RgF836zkyUfAD01Fq+sAk5EwWgLw+nnm5KVNGDu7PRR2kRGDsWvqpo0g== dependencies: "@babel/core" "^7.18.6" "@babel/generator" "^7.18.7" @@ -1385,13 +1346,13 @@ "@babel/runtime" "^7.18.6" "@babel/runtime-corejs3" "^7.18.6" "@babel/traverse" "^7.18.8" - "@docusaurus/cssnano-preset" "2.3.1" - "@docusaurus/logger" "2.3.1" - "@docusaurus/mdx-loader" "2.3.1" + "@docusaurus/cssnano-preset" "2.4.1" + "@docusaurus/logger" "2.4.1" + "@docusaurus/mdx-loader" "2.4.1" "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/utils" "2.3.1" - "@docusaurus/utils-common" "2.3.1" - "@docusaurus/utils-validation" "2.3.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-common" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" "@slorber/static-site-generator-webpack-plugin" "^4.0.7" "@svgr/webpack" "^6.2.1" autoprefixer "^10.4.7" @@ -1447,85 +1408,44 @@ webpack-merge "^5.8.0" webpackbar "^5.0.2" -"@docusaurus/cssnano-preset@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.2.0.tgz#fc05044659051ae74ab4482afcf4a9936e81d523" - integrity sha512-mAAwCo4n66TMWBH1kXnHVZsakW9VAXJzTO4yZukuL3ro4F+JtkMwKfh42EG75K/J/YIFQG5I/Bzy0UH/hFxaTg== - dependencies: - cssnano-preset-advanced "^5.3.8" - postcss "^8.4.14" - postcss-sort-media-queries "^4.2.1" - tslib "^2.4.0" - -"@docusaurus/cssnano-preset@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.3.1.tgz#e042487655e3e062417855e12edb3f6eee8f5ecb" - integrity sha512-7mIhAROES6CY1GmCjR4CZkUfjTL6B3u6rKHK0ChQl2d1IevYXq/k/vFgvOrJfcKxiObpMnE9+X6R2Wt1KqxC6w== +"@docusaurus/cssnano-preset@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.1.tgz#eacadefb1e2e0f59df3467a0fe83e4ff79eed163" + integrity sha512-ka+vqXwtcW1NbXxWsh6yA1Ckii1klY9E53cJ4O9J09nkMBgrNX3iEFED1fWdv8wf4mJjvGi5RLZ2p9hJNjsLyQ== dependencies: cssnano-preset-advanced "^5.3.8" postcss "^8.4.14" postcss-sort-media-queries "^4.2.1" tslib "^2.4.0" -"@docusaurus/logger@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.2.0.tgz#ea2f7feda7b8675485933b87f06d9c976d17423f" - integrity sha512-DF3j1cA5y2nNsu/vk8AG7xwpZu6f5MKkPPMaaIbgXLnWGfm6+wkOeW7kNrxnM95YOhKUkJUophX69nGUnLsm0A== - dependencies: - chalk "^4.1.2" - tslib "^2.4.0" - -"@docusaurus/logger@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.3.1.tgz#d76aefb452e3734b4e0e645efc6cbfc0aae52869" - integrity sha512-2lAV/olKKVr9qJhfHFCaqBIl8FgYjbUFwgUnX76+cULwQYss+42ZQ3grHGFvI0ocN2X55WcYe64ellQXz7suqg== +"@docusaurus/logger@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.4.1.tgz#4d2c0626b40752641f9fdd93ad9b5a7a0792f767" + integrity sha512-5h5ysIIWYIDHyTVd8BjheZmQZmEgWDR54aQ1BX9pjFfpyzFo5puKXKYrYJXbjEHGyVhEzmB9UXwbxGfaZhOjcg== dependencies: chalk "^4.1.2" tslib "^2.4.0" -"@docusaurus/lqip-loader@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/lqip-loader/-/lqip-loader-2.2.0.tgz#46ccf0da970cd7817c885e09ff14d8bccd64d434" - integrity sha512-nER3YokwkkNA1c2bAQzyqH8nfdbzkNtgwbuWvwnNuxW6kyhMopLcIy9qQYpSzcA0S7xcfj7+ysdB/DX7+nWoMw== +"@docusaurus/lqip-loader@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/lqip-loader/-/lqip-loader-2.4.1.tgz#5e6a279982af898e646f042097fc4053fa15b4b8" + integrity sha512-XJ0z/xSx5HtAQ+/xBoAiRZ7DY9zEP6IImAKlAk6RxuFzyB4HT8eINWN+LwLnOsTh5boIj37JCX+T76bH0ieULA== dependencies: - "@docusaurus/logger" "2.2.0" + "@docusaurus/logger" "2.4.1" file-loader "^6.2.0" lodash "^4.17.21" sharp "^0.30.7" tslib "^2.4.0" -"@docusaurus/mdx-loader@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.2.0.tgz#fd558f429e5d9403d284bd4214e54d9768b041a0" - integrity sha512-X2bzo3T0jW0VhUU+XdQofcEeozXOTmKQMvc8tUnWRdTnCvj4XEcBVdC3g+/jftceluiwSTNRAX4VBOJdNt18jA== - dependencies: - "@babel/parser" "^7.18.8" - "@babel/traverse" "^7.18.8" - "@docusaurus/logger" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@mdx-js/mdx" "^1.6.22" - escape-html "^1.0.3" - file-loader "^6.2.0" - fs-extra "^10.1.0" - image-size "^1.0.1" - mdast-util-to-string "^2.0.0" - remark-emoji "^2.2.0" - stringify-object "^3.3.0" - tslib "^2.4.0" - unified "^9.2.2" - unist-util-visit "^2.0.3" - url-loader "^4.1.1" - webpack "^5.73.0" - -"@docusaurus/mdx-loader@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.3.1.tgz#7ec6acee5eff0a280e1b399ea4dd690b15a793f7" - integrity sha512-Gzga7OsxQRpt3392K9lv/bW4jGppdLFJh3luKRknCKSAaZrmVkOQv2gvCn8LAOSZ3uRg5No7AgYs/vpL8K94lA== +"@docusaurus/mdx-loader@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.4.1.tgz#6425075d7fc136dbfdc121349060cedd64118393" + integrity sha512-4KhUhEavteIAmbBj7LVFnrVYDiU51H5YWW1zY6SmBSte/YLhDutztLTBE0PQl1Grux1jzUJeaSvAzHpTn6JJDQ== dependencies: "@babel/parser" "^7.18.8" "@babel/traverse" "^7.18.8" - "@docusaurus/logger" "2.3.1" - "@docusaurus/utils" "2.3.1" + "@docusaurus/logger" "2.4.1" + "@docusaurus/utils" "2.4.1" "@mdx-js/mdx" "^1.6.22" escape-html "^1.0.3" file-loader "^6.2.0" @@ -1540,27 +1460,13 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@docusaurus/module-type-aliases@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.2.0.tgz#1e23e54a1bbb6fde1961e4fa395b1b69f4803ba5" - integrity sha512-wDGW4IHKoOr9YuJgy7uYuKWrDrSpsUSDHLZnWQYM9fN7D5EpSmYHjFruUpKWVyxLpD/Wh0rW8hYZwdjJIQUQCQ== - dependencies: - "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/types" "2.2.0" - "@types/history" "^4.7.11" - "@types/react" "*" - "@types/react-router-config" "*" - "@types/react-router-dom" "*" - react-helmet-async "*" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - -"@docusaurus/module-type-aliases@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.3.1.tgz#986186200818fed999be2e18d6c698eaf4683a33" - integrity sha512-6KkxfAVOJqIUynTRb/tphYCl+co3cP0PlHiMDbi+SzmYxMdgIrwYqH9yAnGSDoN6Jk2ZE/JY/Azs/8LPgKP48A== +"@docusaurus/module-type-aliases@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.1.tgz#38b3c2d2ae44bea6d57506eccd84280216f0171c" + integrity sha512-gLBuIFM8Dp2XOCWffUDSjtxY7jQgKvYujt7Mx5s4FCTfoL5dN1EVbnrn+O2Wvh8b0a77D57qoIDY7ghgmatR1A== dependencies: "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/types" "2.3.1" + "@docusaurus/types" "2.4.1" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1568,18 +1474,18 @@ react-helmet-async "*" react-loadable "npm:@docusaurus/react-loadable@5.5.2" -"@docusaurus/plugin-content-blog@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.2.0.tgz#dc55982e76771f4e678ac10e26d10e1da2011dc1" - integrity sha512-0mWBinEh0a5J2+8ZJXJXbrCk1tSTNf7Nm4tYAl5h2/xx+PvH/Bnu0V+7mMljYm/1QlDYALNIIaT/JcoZQFUN3w== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/plugin-content-blog@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.1.tgz#c705a8b1a36a34f181dcf43b7770532e4dcdc4a3" + integrity sha512-E2i7Knz5YIbE1XELI6RlTnZnGgS52cUO4BlCiCUCvQHbR+s1xeIWz4C6BtaVnlug0Ccz7nFSksfwDpVlkujg5Q== + dependencies: + "@docusaurus/core" "2.4.1" + "@docusaurus/logger" "2.4.1" + "@docusaurus/mdx-loader" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-common" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" cheerio "^1.0.0-rc.12" feed "^4.2.2" fs-extra "^10.1.0" @@ -1590,18 +1496,18 @@ utility-types "^3.10.0" webpack "^5.73.0" -"@docusaurus/plugin-content-docs@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.2.0.tgz#0fcb85226fcdb80dc1e2d4a36ef442a650dcc84d" - integrity sha512-BOazBR0XjzsHE+2K1wpNxz5QZmrJgmm3+0Re0EVPYFGW8qndCWGNtXW/0lGKhecVPML8yyFeAmnUCIs7xM2wPw== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/module-type-aliases" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/plugin-content-docs@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.1.tgz#ed94d9721b5ce7a956fb01cc06c40d8eee8dfca7" + integrity sha512-Lo7lSIcpswa2Kv4HEeUcGYqaasMUQNpjTXpV0N8G6jXgZaQurqp7E8NGYeGbDXnb48czmHWbzDL4S3+BbK0VzA== + dependencies: + "@docusaurus/core" "2.4.1" + "@docusaurus/logger" "2.4.1" + "@docusaurus/mdx-loader" "2.4.1" + "@docusaurus/module-type-aliases" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" "@types/react-router-config" "^5.0.6" combine-promises "^1.1.0" fs-extra "^10.1.0" @@ -1612,123 +1518,112 @@ utility-types "^3.10.0" webpack "^5.73.0" -"@docusaurus/plugin-content-docs@^2.1.0": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.3.1.tgz#feae1555479558a55182f22f8a07acc5e0d7444d" - integrity sha512-DxztTOBEruv7qFxqUtbsqXeNcHqcVEIEe+NQoI1oi2DBmKBhW/o0MIal8lt+9gvmpx3oYtlwmLOOGepxZgJGkw== - dependencies: - "@docusaurus/core" "2.3.1" - "@docusaurus/logger" "2.3.1" - "@docusaurus/mdx-loader" "2.3.1" - "@docusaurus/module-type-aliases" "2.3.1" - "@docusaurus/types" "2.3.1" - "@docusaurus/utils" "2.3.1" - "@docusaurus/utils-validation" "2.3.1" - "@types/react-router-config" "^5.0.6" - combine-promises "^1.1.0" +"@docusaurus/plugin-content-pages@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.1.tgz#c534f7e49967699a45bbe67050d1605ebbf3d285" + integrity sha512-/UjuH/76KLaUlL+o1OvyORynv6FURzjurSjvn2lbWTFc4tpYY2qLYTlKpTCBVPhlLUQsfyFnshEJDLmPneq2oA== + dependencies: + "@docusaurus/core" "2.4.1" + "@docusaurus/mdx-loader" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" fs-extra "^10.1.0" - import-fresh "^3.3.0" - js-yaml "^4.1.0" - lodash "^4.17.21" tslib "^2.4.0" - utility-types "^3.10.0" webpack "^5.73.0" -"@docusaurus/plugin-content-pages@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.2.0.tgz#e3f40408787bbe229545dd50595f87e1393bc3ae" - integrity sha512-+OTK3FQHk5WMvdelz8v19PbEbx+CNT6VSpx7nVOvMNs5yJCKvmqBJBQ2ZSxROxhVDYn+CZOlmyrC56NSXzHf6g== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/plugin-debug@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.4.1.tgz#461a2c77b0c5a91b2c05257c8f9585412aaa59dc" + integrity sha512-7Yu9UPzRShlrH/G8btOpR0e6INFZr0EegWplMjOqelIwAcx3PKyR8mgPTxGTxcqiYj6hxSCRN0D8R7YrzImwNA== + dependencies: + "@docusaurus/core" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils" "2.4.1" fs-extra "^10.1.0" + react-json-view "^1.21.3" tslib "^2.4.0" - webpack "^5.73.0" -"@docusaurus/plugin-debug@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.2.0.tgz#b38741d2c492f405fee01ee0ef2e0029cedb689a" - integrity sha512-p9vOep8+7OVl6r/NREEYxf4HMAjV8JMYJ7Bos5fCFO0Wyi9AZEo0sCTliRd7R8+dlJXZEgcngSdxAUo/Q+CJow== +"@docusaurus/plugin-google-analytics@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.1.tgz#30de1c35773bf9d52bb2d79b201b23eb98022613" + integrity sha512-dyZJdJiCoL+rcfnm0RPkLt/o732HvLiEwmtoNzOoz9MSZz117UH2J6U2vUDtzUzwtFLIf32KkeyzisbwUCgcaQ== dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - fs-extra "^10.1.0" - react-json-view "^1.21.3" + "@docusaurus/core" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" tslib "^2.4.0" -"@docusaurus/plugin-google-analytics@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.2.0.tgz#63c7137eff5a1208d2059fea04b5207c037d7954" - integrity sha512-+eZVVxVeEnV5nVQJdey9ZsfyEVMls6VyWTIj8SmX0k5EbqGvnIfET+J2pYEuKQnDIHxy+syRMoRM6AHXdHYGIg== +"@docusaurus/plugin-google-gtag@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.1.tgz#6a3eb91022714735e625c7ca70ef5188fa7bd0dc" + integrity sha512-mKIefK+2kGTQBYvloNEKtDmnRD7bxHLsBcxgnbt4oZwzi2nxCGjPX6+9SQO2KCN5HZbNrYmGo5GJfMgoRvy6uA== dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" + "@docusaurus/core" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" tslib "^2.4.0" -"@docusaurus/plugin-google-gtag@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.2.0.tgz#7b086d169ac5fe9a88aca10ab0fd2bf00c6c6b12" - integrity sha512-6SOgczP/dYdkqUMGTRqgxAS1eTp6MnJDAQMy8VCF1QKbWZmlkx4agHDexihqmYyCujTYHqDAhm1hV26EET54NQ== +"@docusaurus/plugin-google-tag-manager@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.1.tgz#b99f71aec00b112bbf509ef2416e404a95eb607e" + integrity sha512-Zg4Ii9CMOLfpeV2nG74lVTWNtisFaH9QNtEw48R5QE1KIwDBdTVaiSA18G1EujZjrzJJzXN79VhINSbOJO/r3g== dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" + "@docusaurus/core" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" tslib "^2.4.0" -"@docusaurus/plugin-ideal-image@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-2.2.0.tgz#bd2fc4d8f8c4a4526b288297d892cb76e61e1382" - integrity sha512-1tnyPotxLEglt497nmccxWOpAA6ulMf4nc2k8tReEljmwHebefWV9wbK1RK/44Na8GiGb709/Zs+HHdNRied8w== +"@docusaurus/plugin-ideal-image@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-2.4.1.tgz#110e9814ad3af66235c849d2e00c9e84f552c961" + integrity sha512-jxvgCGPmHxdae2Y2uskzxIbMCA4WLTfzkufsLbD4mEAjCRIkt6yzux6q5kqKTrO+AxzpANVcJNGmaBtKZGv5aw== dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/lqip-loader" "2.2.0" + "@docusaurus/core" "2.4.1" + "@docusaurus/lqip-loader" "2.4.1" "@docusaurus/responsive-loader" "^1.7.0" - "@docusaurus/theme-translations" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" + "@docusaurus/theme-translations" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" "@endiliey/react-ideal-image" "^0.0.11" react-waypoint "^10.3.0" sharp "^0.30.7" tslib "^2.4.0" webpack "^5.73.0" -"@docusaurus/plugin-sitemap@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.2.0.tgz#876da60937886032d63143253d420db6a4b34773" - integrity sha512-0jAmyRDN/aI265CbWZNZuQpFqiZuo+5otk2MylU9iVrz/4J7gSc+ZJ9cy4EHrEsW7PV8s1w18hIEsmcA1YgkKg== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/plugin-sitemap@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.1.tgz#8a7a76ed69dc3e6b4474b6abb10bb03336a9de6d" + integrity sha512-lZx+ijt/+atQ3FVE8FOHV/+X3kuok688OydDXrqKRJyXBJZKgGjA2Qa8RjQ4f27V2woaXhtnyrdPop/+OjVMRg== + dependencies: + "@docusaurus/core" "2.4.1" + "@docusaurus/logger" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-common" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" fs-extra "^10.1.0" sitemap "^7.1.1" tslib "^2.4.0" -"@docusaurus/preset-classic@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.2.0.tgz#bece5a043eeb74430f7c6c7510000b9c43669eb7" - integrity sha512-yKIWPGNx7BT8v2wjFIWvYrS+nvN04W+UameSFf8lEiJk6pss0kL6SG2MRvyULiI3BDxH+tj6qe02ncpSPGwumg== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/plugin-content-blog" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/plugin-content-pages" "2.2.0" - "@docusaurus/plugin-debug" "2.2.0" - "@docusaurus/plugin-google-analytics" "2.2.0" - "@docusaurus/plugin-google-gtag" "2.2.0" - "@docusaurus/plugin-sitemap" "2.2.0" - "@docusaurus/theme-classic" "2.2.0" - "@docusaurus/theme-common" "2.2.0" - "@docusaurus/theme-search-algolia" "2.2.0" - "@docusaurus/types" "2.2.0" +"@docusaurus/preset-classic@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.4.1.tgz#072f22d0332588e9c5f512d4bded8d7c99f91497" + integrity sha512-P4//+I4zDqQJ+UDgoFrjIFaQ1MeS9UD1cvxVQaI6O7iBmiHQm0MGROP1TbE7HlxlDPXFJjZUK3x3cAoK63smGQ== + dependencies: + "@docusaurus/core" "2.4.1" + "@docusaurus/plugin-content-blog" "2.4.1" + "@docusaurus/plugin-content-docs" "2.4.1" + "@docusaurus/plugin-content-pages" "2.4.1" + "@docusaurus/plugin-debug" "2.4.1" + "@docusaurus/plugin-google-analytics" "2.4.1" + "@docusaurus/plugin-google-gtag" "2.4.1" + "@docusaurus/plugin-google-tag-manager" "2.4.1" + "@docusaurus/plugin-sitemap" "2.4.1" + "@docusaurus/theme-classic" "2.4.1" + "@docusaurus/theme-common" "2.4.1" + "@docusaurus/theme-search-algolia" "2.4.1" + "@docusaurus/types" "2.4.1" "@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": version "5.5.2" @@ -1745,27 +1640,27 @@ dependencies: loader-utils "^2.0.0" -"@docusaurus/theme-classic@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.2.0.tgz#a048bb1bc077dee74b28bec25f4b84b481863742" - integrity sha512-kjbg/qJPwZ6H1CU/i9d4l/LcFgnuzeiGgMQlt6yPqKo0SOJIBMPuz7Rnu3r/WWbZFPi//o8acclacOzmXdUUEg== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/module-type-aliases" "2.2.0" - "@docusaurus/plugin-content-blog" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/plugin-content-pages" "2.2.0" - "@docusaurus/theme-common" "2.2.0" - "@docusaurus/theme-translations" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/theme-classic@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.4.1.tgz#0060cb263c1a73a33ac33f79bb6bc2a12a56ad9e" + integrity sha512-Rz0wKUa+LTW1PLXmwnf8mn85EBzaGSt6qamqtmnh9Hflkc+EqiYMhtUJeLdV+wsgYq4aG0ANc+bpUDpsUhdnwg== + dependencies: + "@docusaurus/core" "2.4.1" + "@docusaurus/mdx-loader" "2.4.1" + "@docusaurus/module-type-aliases" "2.4.1" + "@docusaurus/plugin-content-blog" "2.4.1" + "@docusaurus/plugin-content-docs" "2.4.1" + "@docusaurus/plugin-content-pages" "2.4.1" + "@docusaurus/theme-common" "2.4.1" + "@docusaurus/theme-translations" "2.4.1" + "@docusaurus/types" "2.4.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-common" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" "@mdx-js/react" "^1.6.22" clsx "^1.2.1" copy-text-to-clipboard "^3.0.1" - infima "0.2.0-alpha.42" + infima "0.2.0-alpha.43" lodash "^4.17.21" nprogress "^0.2.0" postcss "^8.4.14" @@ -1776,17 +1671,18 @@ tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-common@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.2.0.tgz#2303498d80448aafdd588b597ce9d6f4cfa930e4" - integrity sha512-R8BnDjYoN90DCL75gP7qYQfSjyitXuP9TdzgsKDmSFPNyrdE3twtPNa2dIN+h+p/pr+PagfxwWbd6dn722A1Dw== - dependencies: - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/module-type-aliases" "2.2.0" - "@docusaurus/plugin-content-blog" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/plugin-content-pages" "2.2.0" - "@docusaurus/utils" "2.2.0" +"@docusaurus/theme-common@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.4.1.tgz#03e16f7aa96455e952f3243ac99757b01a3c83d4" + integrity sha512-G7Zau1W5rQTaFFB3x3soQoZpkgMbl/SYNG8PfMFIjKa3M3q8n0m/GRf5/H/e5BqOvt8c+ZWIXGCiz+kUCSHovA== + dependencies: + "@docusaurus/mdx-loader" "2.4.1" + "@docusaurus/module-type-aliases" "2.4.1" + "@docusaurus/plugin-content-blog" "2.4.1" + "@docusaurus/plugin-content-docs" "2.4.1" + "@docusaurus/plugin-content-pages" "2.4.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-common" "2.4.1" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1794,56 +1690,43 @@ parse-numeric-range "^1.3.0" prism-react-renderer "^1.3.5" tslib "^2.4.0" + use-sync-external-store "^1.2.0" utility-types "^3.10.0" -"@docusaurus/theme-search-algolia@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.2.0.tgz#77fd9f7a600917e6024fe3ac7fb6cfdf2ce84737" - integrity sha512-2h38B0tqlxgR2FZ9LpAkGrpDWVdXZ7vltfmTdX+4RsDs3A7khiNsmZB+x/x6sA4+G2V2CvrsPMlsYBy5X+cY1w== +"@docusaurus/theme-search-algolia@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.1.tgz#906bd2cca3fced0241985ef502c892f58ff380fc" + integrity sha512-6BcqW2lnLhZCXuMAvPRezFs1DpmEKzXFKlYjruuas+Xy3AQeFzDJKTJFIm49N77WFCTyxff8d3E4Q9pi/+5McQ== dependencies: "@docsearch/react" "^3.1.1" - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/theme-common" "2.2.0" - "@docusaurus/theme-translations" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" + "@docusaurus/core" "2.4.1" + "@docusaurus/logger" "2.4.1" + "@docusaurus/plugin-content-docs" "2.4.1" + "@docusaurus/theme-common" "2.4.1" + "@docusaurus/theme-translations" "2.4.1" + "@docusaurus/utils" "2.4.1" + "@docusaurus/utils-validation" "2.4.1" algoliasearch "^4.13.1" algoliasearch-helper "^3.10.0" clsx "^1.2.1" - eta "^1.12.3" + eta "^2.0.0" fs-extra "^10.1.0" lodash "^4.17.21" tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.2.0.tgz#5fbd4693679806f80c26eeae1381e1f2c23d83e7" - integrity sha512-3T140AG11OjJrtKlY4pMZ5BzbGRDjNs2co5hJ6uYJG1bVWlhcaFGqkaZ5lCgKflaNHD7UHBHU9Ec5f69jTdd6w== +"@docusaurus/theme-translations@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.4.1.tgz#4d49df5865dae9ef4b98a19284ede62ae6f98726" + integrity sha512-T1RAGP+f86CA1kfE8ejZ3T3pUU3XcyvrGMfC/zxCtc2BsnoexuNI9Vk2CmuKCb+Tacvhxjv5unhxXce0+NKyvA== dependencies: fs-extra "^10.1.0" tslib "^2.4.0" -"@docusaurus/types@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.2.0.tgz#02c577a4041ab7d058a3c214ccb13647e21a9857" - integrity sha512-b6xxyoexfbRNRI8gjblzVOnLr4peCJhGbYGPpJ3LFqpi5nsFfoK4mmDLvWdeah0B7gmJeXabN7nQkFoqeSdmOw== - dependencies: - "@types/history" "^4.7.11" - "@types/react" "*" - commander "^5.1.0" - joi "^17.6.0" - react-helmet-async "^1.3.0" - utility-types "^3.10.0" - webpack "^5.73.0" - webpack-merge "^5.8.0" - -"@docusaurus/types@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.3.1.tgz#785ade2e0f4e35e1eb7fb0d04c27d11c3991a2e8" - integrity sha512-PREbIRhTaNNY042qmfSE372Jb7djZt+oVTZkoqHJ8eff8vOIc2zqqDqBVc5BhOfpZGPTrE078yy/torUEZy08A== +"@docusaurus/types@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.4.1.tgz#d8e82f9e0f704984f98df1f93d6b4554d5458705" + integrity sha512-0R+cbhpMkhbRXX138UOc/2XZFF8hiZa6ooZAEEJFp5scytzCw4tC1gChMFXrpa3d2tYE6AX8IrOEpSonLmfQuQ== dependencies: "@types/history" "^4.7.11" "@types/react" "*" @@ -1854,69 +1737,30 @@ webpack "^5.73.0" webpack-merge "^5.8.0" -"@docusaurus/utils-common@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.2.0.tgz#a401c1b93a8697dd566baf6ac64f0fdff1641a78" - integrity sha512-qebnerHp+cyovdUseDQyYFvMW1n1nv61zGe5JJfoNQUnjKuApch3IVsz+/lZ9a38pId8kqehC1Ao2bW/s0ntDA== - dependencies: - tslib "^2.4.0" - -"@docusaurus/utils-common@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.3.1.tgz#1abe66846eb641547e4964d44f3011938e58e50b" - integrity sha512-pVlRpXkdNcxmKNxAaB1ya2hfCEvVsLDp2joeM6K6uv55Oc5nVIqgyYSgSNKZyMdw66NnvMfsu0RBylcwZQKo9A== - dependencies: - tslib "^2.4.0" - -"@docusaurus/utils-validation@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.2.0.tgz#04d4d103137ad0145883971d3aa497f4a1315f25" - integrity sha512-I1hcsG3yoCkasOL5qQAYAfnmVoLei7apugT6m4crQjmDGxq+UkiRrq55UqmDDyZlac/6ax/JC0p+usZ6W4nVyg== +"@docusaurus/utils-common@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.4.1.tgz#7f72e873e49bd5179588869cc3ab7449a56aae63" + integrity sha512-bCVGdZU+z/qVcIiEQdyx0K13OC5mYwxhSuDUR95oFbKVuXYRrTVrwZIqQljuo1fyJvFTKHiL9L9skQOPokuFNQ== dependencies: - "@docusaurus/logger" "2.2.0" - "@docusaurus/utils" "2.2.0" - joi "^17.6.0" - js-yaml "^4.1.0" tslib "^2.4.0" -"@docusaurus/utils-validation@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.3.1.tgz#b65c718ba9b84b7a891bccf5ac6d19b57ee7d887" - integrity sha512-7n0208IG3k1HVTByMHlZoIDjjOFC8sbViHVXJx0r3Q+3Ezrx+VQ1RZ/zjNn6lT+QBCRCXlnlaoJ8ug4HIVgQ3w== +"@docusaurus/utils-validation@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.4.1.tgz#19959856d4a886af0c5cfb357f4ef68b51151244" + integrity sha512-unII3hlJlDwZ3w8U+pMO3Lx3RhI4YEbY3YNsQj4yzrkZzlpqZOLuAiZK2JyULnD+TKbceKU0WyWkQXtYbLNDFA== dependencies: - "@docusaurus/logger" "2.3.1" - "@docusaurus/utils" "2.3.1" + "@docusaurus/logger" "2.4.1" + "@docusaurus/utils" "2.4.1" joi "^17.6.0" js-yaml "^4.1.0" tslib "^2.4.0" -"@docusaurus/utils@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.2.0.tgz#3d6f9b7a69168d5c92d371bf21c556a4f50d1da6" - integrity sha512-oNk3cjvx7Tt1Lgh/aeZAmFpGV2pDr5nHKrBVx6hTkzGhrnMuQqLt6UPlQjdYQ3QHXwyF/ZtZMO1D5Pfi0lu7SA== - dependencies: - "@docusaurus/logger" "2.2.0" - "@svgr/webpack" "^6.2.1" - file-loader "^6.2.0" - fs-extra "^10.1.0" - github-slugger "^1.4.0" - globby "^11.1.0" - gray-matter "^4.0.3" - js-yaml "^4.1.0" - lodash "^4.17.21" - micromatch "^4.0.5" - resolve-pathname "^3.0.0" - shelljs "^0.8.5" - tslib "^2.4.0" - url-loader "^4.1.1" - webpack "^5.73.0" - -"@docusaurus/utils@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.3.1.tgz#24b9cae3a23b1e6dc88f95c45722c7e82727b032" - integrity sha512-9WcQROCV0MmrpOQDXDGhtGMd52DHpSFbKLfkyaYumzbTstrbA5pPOtiGtxK1nqUHkiIv8UwexS54p0Vod2I1lg== +"@docusaurus/utils@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.4.1.tgz#9c5f76eae37b71f3819c1c1f0e26e6807c99a4fc" + integrity sha512-1lvEZdAQhKNht9aPXPoh69eeKnV0/62ROhQeFKKxmzd0zkcuE/Oc5Gpnt00y/f5bIsmOsYMY7Pqfm/5rteT5GA== dependencies: - "@docusaurus/logger" "2.3.1" + "@docusaurus/logger" "2.4.1" "@svgr/webpack" "^6.2.1" escape-string-regexp "^4.0.0" file-loader "^6.2.0" @@ -1981,13 +1825,13 @@ tslib "~2.1.0" "@graphql-tools/import@^6.2.6": - version "6.5.6" - resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.5.6.tgz#9ea073d7fb4fdd177ecc2df4c553b61db9d55fcb" - integrity sha512-SxCpNhN3sIZM4wsMjQWXKkff/CBn7+WHoZ9OjZkdV5nxGbnzRKh5SZAAsvAFuj6Kst5Y9mlAaiwy+QufZZ1F1w== + version "6.7.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.7.18.tgz#ad092d8a4546bb6ffc3e871e499eec7ac368680b" + integrity sha512-XQDdyZTp+FYmT7as3xRWH/x8dx0QZA2WZqfMF5EWb36a0PiH7WwlRQYIdyYXj8YCLpiWkeBXgBRHmMnwEYR8iQ== dependencies: - "@graphql-tools/utils" "8.5.0" + "@graphql-tools/utils" "^9.2.1" resolve-from "5.0.0" - tslib "~2.3.0" + tslib "^2.4.0" "@graphql-tools/json-file-loader@^6.2.6": version "6.2.6" @@ -2012,6 +1856,14 @@ unixify "1.0.0" valid-url "1.0.9" +"@graphql-tools/merge@8.3.1": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.3.1.tgz#06121942ad28982a14635dbc87b5d488a041d722" + integrity sha512-BMm99mqdNZbEYeTPK3it9r9S6rsZsQKtlqJsSBknAclXq2pGEfOxjcIZi+kBSkHZKPKCRrYDd5vY0+rUmIHVLg== + dependencies: + "@graphql-tools/utils" "8.9.0" + tslib "^2.4.0" + "@graphql-tools/merge@^6.2.12": version "6.2.17" resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-6.2.17.tgz#4dedf87d8435a5e1091d7cc8d4f371ed1e029f1f" @@ -2021,14 +1873,6 @@ "@graphql-tools/utils" "8.0.2" tslib "~2.3.0" -"@graphql-tools/merge@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.0.tgz#8f6638eeecf19f59fef28598024308e0452dd0a2" - integrity sha512-nfMLYF7zczjnIbChZtqbvozRfuRweMD1Fe9HHd4RXd3Tcsj6E17srW0QJfxUoIIWh4pitj+XwZAwhj1PWBDU7g== - dependencies: - "@graphql-tools/utils" "^8.4.0" - tslib "~2.3.0" - "@graphql-tools/schema@^7.1.5": version "7.1.5" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-7.1.5.tgz#07b24e52b182e736a6b77c829fc48b84d89aa711" @@ -2039,13 +1883,13 @@ value-or-promise "1.0.6" "@graphql-tools/schema@^8.0.2": - version "8.3.0" - resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.3.0.tgz#ddf4297859c6d7ac1ebbbd91460260ed424115db" - integrity sha512-OJD4Q1Xa3sffRiHzy0sskZz9ZWeqaujINfoim4CTk5Y9es1LS+WnKi25wVhmL2SGzzmKuAv7oDn+dpQAlM+Gfw== + version "8.5.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.5.1.tgz#c2f2ff1448380919a330312399c9471db2580b58" + integrity sha512-0Esilsh0P/qYcB5DKQpiKeQs/jevzIadNTaT0jeWklPMwNbT7yMX4EqZany7mbeRRlSRwMzNzL5olyFdffHBZg== dependencies: - "@graphql-tools/merge" "^8.2.0" - "@graphql-tools/utils" "^8.4.0" - tslib "~2.3.0" + "@graphql-tools/merge" "8.3.1" + "@graphql-tools/utils" "8.9.0" + tslib "^2.4.0" value-or-promise "1.0.11" "@graphql-tools/url-loader@^6.8.2": @@ -2080,12 +1924,12 @@ dependencies: tslib "~2.3.0" -"@graphql-tools/utils@8.5.0", "@graphql-tools/utils@^8.4.0": - version "8.5.0" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.5.0.tgz#439487ac756d9458a33091e5e0435ddf8e794f3e" - integrity sha512-jMwLm6YdN+Vbqntg5GHqDvGLpLa/xPSpRs/c40d0rBuel77wo7AaQ8jHeBSpp9y+7kp7HrGSWff1u7yJ7F8ppw== +"@graphql-tools/utils@8.9.0": + version "8.9.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.9.0.tgz#c6aa5f651c9c99e1aca55510af21b56ec296cdb7" + integrity sha512-pjJIWH0XOVnYGXCqej8g/u/tsfV4LvLlj0eATKQu5zwnxd/TiTHq7Cg313qUPTFFHZ3PP5wJ15chYVtLDwaymg== dependencies: - tslib "~2.3.0" + tslib "^2.4.0" "@graphql-tools/utils@^7.0.0", "@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.5.0", "@graphql-tools/utils@^7.7.0", "@graphql-tools/utils@^7.7.1", "@graphql-tools/utils@^7.8.1", "@graphql-tools/utils@^7.9.0": version "7.10.0" @@ -2096,6 +1940,14 @@ camel-case "4.1.2" tslib "~2.2.0" +"@graphql-tools/utils@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-9.2.1.tgz#1b3df0ef166cfa3eae706e3518b17d5922721c57" + integrity sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + tslib "^2.4.0" + "@graphql-tools/wrap@^7.0.4": version "7.0.8" resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-7.0.8.tgz#ad41e487135ca3ea1ae0ea04bb3f596177fb4f50" @@ -2107,10 +1959,15 @@ tslib "~2.2.0" value-or-promise "1.0.6" +"@graphql-typed-document-node/core@^3.1.1": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@hapi/hoek@^9.0.0": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" - integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== "@hapi/topo@^5.0.0": version "5.1.0" @@ -2119,63 +1976,82 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@sinclair/typebox" "^0.27.8" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": +"@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== +"@jridgewell/source-map@^0.3.3": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" - integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.19" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== "@markprompt/core@^0.4.5": - version "0.4.5" - resolved "https://registry.yarnpkg.com/@markprompt/core/-/core-0.4.5.tgz#356b7ad57a893b52076efe073db182a2d94e7fa9" - integrity sha512-HIHzD63KoisI5W7EYlz3b5uukjDBaxV9kIiqCXgPSw5aJnjLOazT2iFAI+bF2UX4xWFu2sE3RSg/JOjKdv15Dw== + version "0.4.6" + resolved "https://registry.yarnpkg.com/@markprompt/core/-/core-0.4.6.tgz#e68ad70704ae41a909c67de511063f3460e3c1d8" + integrity sha512-xqpIcrL9LTbhn0LMQNyVr503rotDvVI6jIJJC+z2h17zFXN3sxPG/sbX7UjR5xPcJuF5zLxzm1fqrBFZALAYxg== "@markprompt/react@^0.3.5": version "0.3.5" @@ -2256,13 +2132,13 @@ "@octokit/types" "^6.0.3" "@octokit/core@^3.5.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b" - integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" + integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== dependencies: "@octokit/auth-token" "^2.4.4" "@octokit/graphql" "^4.5.8" - "@octokit/request" "^5.6.0" + "@octokit/request" "^5.6.3" "@octokit/request-error" "^2.0.5" "@octokit/types" "^6.0.3" before-after-hook "^2.2.0" @@ -2286,17 +2162,17 @@ "@octokit/types" "^6.0.3" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^11.2.0": - version "11.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" - integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== +"@octokit/openapi-types@^12.11.0": + version "12.11.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" + integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== "@octokit/plugin-paginate-rest@^2.16.8": - version "2.17.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz#32e9c7cab2a374421d3d0de239102287d791bce7" - integrity sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw== + version "2.21.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e" + integrity sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw== dependencies: - "@octokit/types" "^6.34.0" + "@octokit/types" "^6.40.0" "@octokit/plugin-request-log@^1.0.4": version "1.0.4" @@ -2304,11 +2180,11 @@ integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== "@octokit/plugin-rest-endpoint-methods@^5.12.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz#8c46109021a3412233f6f50d28786f8e552427ba" - integrity sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA== + version "5.16.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342" + integrity sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw== dependencies: - "@octokit/types" "^6.34.0" + "@octokit/types" "^6.39.0" deprecation "^2.3.1" "@octokit/plugin-retry@^3.0.9": @@ -2320,9 +2196,9 @@ bottleneck "^2.15.3" "@octokit/plugin-throttling@^3.5.1": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-3.5.2.tgz#8b1797a5f14edbca0b8af619394056ed0ed5c9b5" - integrity sha512-Eu7kfJxU8vmHqWGNszWpg+GVp2tnAfax3XQV5CkYPEE69C+KvInJXW9WajgSeW+cxYe0UVdouzCtcreGNuJo7A== + version "3.7.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz#a35cd05de22b2ef13fde45390d983ff8365b9a9e" + integrity sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow== dependencies: "@octokit/types" "^6.0.1" bottleneck "^2.15.3" @@ -2336,16 +2212,16 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request@^5.6.0": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" - integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== +"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": + version "5.6.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" + integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.1.0" "@octokit/types" "^6.16.1" is-plain-object "^5.0.0" - node-fetch "^2.6.1" + node-fetch "^2.6.7" universal-user-agent "^6.0.0" "@octokit/rest@^18.6.2": @@ -2358,195 +2234,235 @@ "@octokit/plugin-request-log" "^1.0.4" "@octokit/plugin-rest-endpoint-methods" "^5.12.0" -"@octokit/types@^6.0.1", "@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.34.0": - version "6.34.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218" - integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw== +"@octokit/types@^6.0.1", "@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0": + version "6.41.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" + integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== dependencies: - "@octokit/openapi-types" "^11.2.0" + "@octokit/openapi-types" "^12.11.0" "@polka/url@^1.0.0-next.20": version "1.0.0-next.21" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== -"@radix-ui/primitive@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.0.tgz#e1d8ef30b10ea10e69c76e896f608d9276352253" - integrity sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA== +"@radix-ui/primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" + integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-compose-refs@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz#37595b1f16ec7f228d698590e78eeed18ff218ae" - integrity sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA== +"@radix-ui/react-compose-refs@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" + integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-context@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0" - integrity sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg== +"@radix-ui/react-context@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" + integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== dependencies: "@babel/runtime" "^7.13.10" "@radix-ui/react-dialog@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.3.tgz#a715bf30f35fcd80476c0a07fcc073c1968e6d3e" - integrity sha512-owNhq36kNPqC2/a+zJRioPg6HHnTn5B/sh/NjTY8r4W9g1L5VJlrzZIVcBr7R9Mg8iLjVmh6MGgMlfoVf/WO/A== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.4.tgz#06bce6c16bb93eb36d7a8589e665a20f4c1c52c1" + integrity sha512-hJtRy/jPULGQZceSAP2Re6/4NpKo8im6V8P2hUqZsdFiSL8l35kYsw3qbRI6Ay5mQd2+wlLqje770eq+RJ3yZg== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-dismissable-layer" "1.0.3" - "@radix-ui/react-focus-guards" "1.0.0" - "@radix-ui/react-focus-scope" "1.0.2" - "@radix-ui/react-id" "1.0.0" - "@radix-ui/react-portal" "1.0.2" - "@radix-ui/react-presence" "1.0.0" - "@radix-ui/react-primitive" "1.0.2" - "@radix-ui/react-slot" "1.0.1" - "@radix-ui/react-use-controllable-state" "1.0.0" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" aria-hidden "^1.1.1" react-remove-scroll "2.5.5" -"@radix-ui/react-dismissable-layer@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.3.tgz#63844d8e6bbcd010a513e7176d051c3c4044e09e" - integrity sha512-nXZOvFjOuHS1ovumntGV7NNoLaEp9JEvTht3MBjP44NSW5hUKj/8OnfN3+8WmB+CEhN44XaGhpHoSsUIEl5P7Q== +"@radix-ui/react-dismissable-layer@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz#883a48f5f938fa679427aa17fcba70c5494c6978" + integrity sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.2" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-escape-keydown" "1.0.2" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-escape-keydown" "1.0.3" -"@radix-ui/react-focus-guards@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa" - integrity sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ== +"@radix-ui/react-focus-guards@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" + integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA== dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-focus-scope@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.2.tgz#5fe129cbdb5986d0a3ae16d14c473c243fe3bc79" - integrity sha512-spwXlNTfeIprt+kaEWE/qYuYT3ZAqJiAGjN/JgdvgVDTu8yc+HuX+WOWXrKliKnLnwck0F6JDkqIERncnih+4A== +"@radix-ui/react-focus-scope@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz#9c2e8d4ed1189a1d419ee61edd5c1828726472f9" + integrity sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.2" - "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" -"@radix-ui/react-id@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.0.tgz#8d43224910741870a45a8c9d092f25887bb6d11e" - integrity sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw== +"@radix-ui/react-id@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0" + integrity sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.1" -"@radix-ui/react-portal@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.2.tgz#102370b1027a767a371cab0243be4bc664f72330" - integrity sha512-swu32idoCW7KA2VEiUZGBSu9nB6qwGdV6k6HYhUoOo3M1FFpD+VgLzUqtt3mwL1ssz7r2x8MggpLSQach2Xy/Q== +"@radix-ui/react-portal@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.3.tgz#ffb961244c8ed1b46f039e6c215a6c4d9989bda1" + integrity sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.2" + "@radix-ui/react-primitive" "1.0.3" -"@radix-ui/react-presence@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.0.tgz#814fe46df11f9a468808a6010e3f3ca7e0b2e84a" - integrity sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w== +"@radix-ui/react-presence@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" + integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" -"@radix-ui/react-primitive@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz#54e22f49ca59ba88d8143090276d50b93f8a7053" - integrity sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw== +"@radix-ui/react-primitive@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" + integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-slot" "1.0.1" + "@radix-ui/react-slot" "1.0.2" -"@radix-ui/react-slot@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.1.tgz#e7868c669c974d649070e9ecbec0b367ee0b4d81" - integrity sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw== +"@radix-ui/react-slot@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" + integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.1" -"@radix-ui/react-use-callback-ref@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz#9e7b8b6b4946fe3cbe8f748c82a2cce54e7b6a90" - integrity sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg== +"@radix-ui/react-use-callback-ref@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" + integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-use-controllable-state@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz#a64deaafbbc52d5d407afaa22d493d687c538b7f" - integrity sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg== +"@radix-ui/react-use-controllable-state@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" + integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.0.1" -"@radix-ui/react-use-escape-keydown@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" - integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA== +"@radix-ui/react-use-escape-keydown@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" + integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.0.1" -"@radix-ui/react-use-layout-effect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz#2fc19e97223a81de64cd3ba1dc42ceffd82374dc" - integrity sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ== +"@radix-ui/react-use-layout-effect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" + integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== dependencies: "@babel/runtime" "^7.13.10" "@radix-ui/react-visually-hidden@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.2.tgz#29b117a59ef09a984bdad12cb98d81e8350be450" - integrity sha512-qirnJxtYn73HEk1rXL12/mXnu2rwsNHDID10th2JGtdK25T9wX+mxRmGt7iPSahw512GbZOc0syZX1nLQGoEOg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz#51aed9dd0fe5abcad7dee2a234ad36106a6984ac" + integrity sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA== dependencies: "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.2" + "@radix-ui/react-primitive" "1.0.3" + +"@rc-component/color-picker@~1.4.0": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@rc-component/color-picker/-/color-picker-1.4.1.tgz#dcab0b660e9c4ed63a7582db68ed4a77c862cb93" + integrity sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw== + dependencies: + "@babel/runtime" "^7.10.1" + "@ctrl/tinycolor" "^3.6.0" + classnames "^2.2.6" + rc-util "^5.30.0" + +"@rc-component/context@^1.3.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@rc-component/context/-/context-1.4.0.tgz#dc6fb021d6773546af8f016ae4ce9aea088395e8" + integrity sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w== + dependencies: + "@babel/runtime" "^7.10.1" + rc-util "^5.27.0" "@rc-component/mini-decimal@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@rc-component/mini-decimal/-/mini-decimal-1.0.1.tgz#e5dbc20a6a5b0e234d279bc71ce730ab865d3910" - integrity sha512-9N8nRk0oKj1qJzANKl+n9eNSMUGsZtjwNuDCiZ/KA+dt1fE3zq5x2XxclRcAbOIXnZcJ53ozP2Pa60gyELXagA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz#7b7a362b14a0a54cb5bc6fd2b82731f29f11d9b0" + integrity sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ== dependencies: "@babel/runtime" "^7.18.0" -"@rc-component/portal@^1.0.0-6", "@rc-component/portal@^1.0.0-8", "@rc-component/portal@^1.0.0-9", "@rc-component/portal@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@rc-component/portal/-/portal-1.0.3.tgz#3aa2c229a7a20ac2412d864e8977e6377973416e" - integrity sha512-rG9j7OMiI9eLFLF6G0B4OcfLac9W8Z7Vjeizbjt/A6R+zzw7vhHbJ4GIkrDpUqXDvFdEEzdxfICpb8/noLwG+w== +"@rc-component/mutate-observer@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz#ee53cc88b78aade3cd0653609215a44779386fd8" + integrity sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw== dependencies: "@babel/runtime" "^7.18.0" classnames "^2.3.2" rc-util "^5.24.4" -"@rc-component/tour@~1.0.1-2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@rc-component/tour/-/tour-1.0.4.tgz#551cdffbd9de0bfe82600f25f73452631cc29a37" - integrity sha512-FwAh9twryS6Ava2mUqwJtbhIt0ObIZIgQOJK+XTl+pQvsmXtUGtbOif3/4FeVmncy7FEGH7mnlIjS4OLGkQC9A== +"@rc-component/portal@^1.0.0-8", "@rc-component/portal@^1.0.0-9", "@rc-component/portal@^1.0.2", "@rc-component/portal@^1.1.0", "@rc-component/portal@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@rc-component/portal/-/portal-1.1.2.tgz#55db1e51d784e034442e9700536faaa6ab63fc71" + integrity sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg== + dependencies: + "@babel/runtime" "^7.18.0" + classnames "^2.3.2" + rc-util "^5.24.4" + +"@rc-component/tour@~1.8.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@rc-component/tour/-/tour-1.8.1.tgz#a820714b66cb17f317ebd21ac1b45733d2b99183" + integrity sha512-CsrQnfKgNArxx2j1RNHVLZgVA+rLrEj06lIsl4KSynMqADsqz8eKvVkr0F3p9PA10948M6WEEZt5a/FGAbGR2A== dependencies: "@babel/runtime" "^7.18.0" "@rc-component/portal" "^1.0.0-9" + "@rc-component/trigger" "^1.3.6" classnames "^2.3.2" - rc-trigger "^5.3.4" rc-util "^5.24.4" +"@rc-component/trigger@^1.0.4", "@rc-component/trigger@^1.15.0", "@rc-component/trigger@^1.3.6", "@rc-component/trigger@^1.5.0", "@rc-component/trigger@^1.6.2", "@rc-component/trigger@^1.7.0": + version "1.15.6" + resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-1.15.6.tgz#ccb71f16229e832e15b3869817cbe24f5e59b54c" + integrity sha512-Tl19KaGsShf4yzqxumsXVT4c7j0l20Dxe5hgP5S0HmxyhCg3oKen28ntGavRCIPW7cl7wgsGotntqcIokgDHzg== + dependencies: + "@babel/runtime" "^7.18.3" + "@rc-component/portal" "^1.1.0" + classnames "^2.3.2" + rc-align "^4.0.0" + rc-motion "^2.0.0" + rc-resize-observer "^1.3.1" + rc-util "^5.33.0" + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -2554,7 +2470,7 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@sideway/formula@^3.0.0": +"@sideway/formula@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== @@ -2564,6 +2480,11 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -2578,20 +2499,76 @@ p-map "^4.0.0" webpack-sources "^3.2.2" +"@supabase/functions-js@^2.1.0": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.1.4.tgz#57da24829ffe8f15c002dfcc615ef4ab5735156d" + integrity sha512-5EEhei1hFCMBX4Pig4kGKjJ59DZvXwilcIBYYp4wyK/iHdAN6Vw9di9VN6/oRXRVS/6jgZd0jdmI+QgGGSxZsA== + dependencies: + cross-fetch "^3.1.5" + +"@supabase/gotrue-js@^2.46.1": + version "2.48.1" + resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-2.48.1.tgz#f7f0e8c27e22215a59e99f8ac07254742bdafcc6" + integrity sha512-jTcqA/iz2crq2b3PbzXZrW3QIoKJ7SfwPWTGJNv//1nDi0i2vCx1mO+BjXwPx+TlOSG8okK0QB2eP8uaF83OvA== + dependencies: + cross-fetch "^3.1.5" + +"@supabase/node-fetch@^2.6.14": + version "2.6.14" + resolved "https://registry.yarnpkg.com/@supabase/node-fetch/-/node-fetch-2.6.14.tgz#6a3e2924e3de8aeeb82c193c786ffb25da9af23f" + integrity sha512-w/Tsd22e/5fAeoxqQ4P2MX6EyF+iM6rc9kmlMVFkHuG0rAltt2TLhFbDJfemnHbtvnazWaRfy5KnFU/SYT37dQ== + dependencies: + whatwg-url "^5.0.0" + +"@supabase/postgrest-js@^1.8.0": + version "1.8.4" + resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.8.4.tgz#89e8355503979ad25e7340b910d17704507ab325" + integrity sha512-ELjpvhb04wILUiJz9zIsTSwaz9LQNlX+Ig5/LgXQ7k68qQI6NqHVn+ISRNt53DngUIyOnLHjeqqIRHBZ7zpgGA== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/realtime-js@^2.7.4": + version "2.7.4" + resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.7.4.tgz#de41195bd3f2cdd6db82d9f93c4c5b8fae9f809b" + integrity sha512-FzSzs1k9ruh/uds5AJ95Nc3beiMCCIhougExJ3O98CX1LMLAKUKFy5FivKLvcNhXnNfUEL0XUfGMb4UH2J7alg== + dependencies: + "@types/phoenix" "^1.5.4" + "@types/websocket" "^1.0.3" + websocket "^1.0.34" + +"@supabase/storage-js@^2.5.1": + version "2.5.3" + resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.5.3.tgz#6d6023d0420151a4c65339e762eca7838fd0f97c" + integrity sha512-wyCkBFMTiehvyLUvvvSszvhPkhaHKHcPx//fYN8NoKEa1TQwC2HuO5EIaJ5EagtAVmI1N3EFQ+M4RER6mnTaNg== + dependencies: + cross-fetch "^3.1.5" + +"@supabase/supabase-js@^2.33.1": + version "2.33.1" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.33.1.tgz#2407861afe63c2817d030514c87a745f78dfe68a" + integrity sha512-jA00rquPTppPOHpBB6KABW98lfg0gYXcuGqP3TB1iiduznRVsi3GGk2qBKXPDLMYSe0kRlQp5xCwWWthaJr8eA== + dependencies: + "@supabase/functions-js" "^2.1.0" + "@supabase/gotrue-js" "^2.46.1" + "@supabase/postgrest-js" "^1.8.0" + "@supabase/realtime-js" "^2.7.4" + "@supabase/storage-js" "^2.5.1" + cross-fetch "^3.1.5" + "@svgr/babel-plugin-add-jsx-attribute@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== "@svgr/babel-plugin-remove-jsx-attribute@*": - version "6.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.5.0.tgz#652bfd4ed0a0699843585cda96faeb09d6e1306e" - integrity sha512-8zYdkym7qNyfXpWvu4yq46k41pyNM9SOstoWhKlm+IfdCE1DdnRKeMUPsWIEO/DEkaWxJ8T9esNdG3QwQ93jBA== + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz#69177f7937233caca3a1afb051906698f2f59186" + integrity sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA== "@svgr/babel-plugin-remove-jsx-empty-expression@*": - version "6.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.5.0.tgz#4b78994ab7d39032c729903fc2dd5c0fa4565cb8" - integrity sha512-NFdxMq3xA42Kb1UbzCVxplUc0iqSyM9X8kopImvFnB+uSDdzIHOdbs1op8ofAvVRtbg4oZiyRl3fTYeKcOe9Iw== + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz#c2c48104cfd7dcd557f373b70a56e9e3bdae1d44" + integrity sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA== "@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": version "6.5.1" @@ -2691,10 +2668,30 @@ dependencies: defer-to-connect "^1.0.1" -"@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@trysound/sax@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" + integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@types/body-parser@*": version "1.19.2" @@ -2712,9 +2709,9 @@ "@types/node" "*" "@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41" + integrity sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig== dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" @@ -2727,9 +2724,9 @@ "@types/node" "*" "@types/debug@^4.0.0": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" - integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + version "4.1.8" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.8.tgz#cef723a5d0a90990313faec2d1e22aee5eecb317" + integrity sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ== dependencies: "@types/ms" "*" @@ -2742,43 +2739,44 @@ "@types/estree" "*" "@types/eslint@*": - version "7.28.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.1.tgz#50b07747f1f84c2ba8cd394cf0fe0ba07afce320" - integrity sha512-XhZKznR3i/W5dXqUhgU9fFdJekufbeBd5DALmkuXoeFcjbQcPk+2cL+WLHf6Q81HWAnM2vrslIHpGVyCAviRwg== + version "8.44.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.2.tgz#0d21c505f98a89b8dd4d37fa162b09da6089199a" + integrity sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" + integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== -"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - version "4.17.30" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz#0f2f99617fa8f9696170c46152ccf7500b34ac04" - integrity sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ== +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.17.36" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz#baa9022119bdc05a4adfe740ffc97b5f9360e545" + integrity sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" + "@types/send" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== dependencies: "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" + "@types/express-serve-static-core" "^4.17.33" "@types/qs" "*" "@types/serve-static" "*" "@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + version "2.3.5" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.5.tgz#08caac88b44d0fdd04dc17a19142355f43bd8a7a" + integrity sha512-SvQi0L/lNpThgPoleH53cdjB3y9zpLlVjRbqB3rH8hx1jiRSBGAhyjV3H+URFjNVRqt2EdYNrbZE5IsGlNfpRg== dependencies: - "@types/unist" "*" + "@types/unist" "^2" "@types/history@^4.7.11": version "4.7.11" @@ -2786,21 +2784,45 @@ integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== "@types/html-minifier-terser@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.0.0.tgz#563c1c6c132cd204e71512f9c0b394ff90d3fae7" - integrity sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ== + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + +"@types/http-errors@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65" + integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ== "@types/http-proxy@^1.17.8": - version "1.17.9" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" - integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== + version "1.17.11" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.11.tgz#0ca21949a5588d55ac2b659b69035c84bd5da293" + integrity sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA== dependencies: "@types/node" "*" +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== "@types/marked@^2.0.2": version "2.0.5" @@ -2808,23 +2830,33 @@ integrity sha512-shRZ7XnYFD/8n8zSjKvFdto1QNSf4tONZIlNEZGrJe8GsOE8DL/hG1Hbl8gZlfLnjS7+f5tZGIaTgfpyW38h4w== "@types/mdast@^3.0.0": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + version "3.0.12" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.12.tgz#beeb511b977c875a5b0cc92eab6fcac2f0895514" + integrity sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg== dependencies: - "@types/unist" "*" + "@types/unist" "^2" "@types/mime@*": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + "@types/ms@*": version "0.7.31" resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/node@*", "@types/node@^17.0.5": +"@types/node@*": + version "20.5.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377" + integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA== + +"@types/node@^17.0.5": version "17.0.45" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== @@ -2839,15 +2871,20 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== +"@types/phoenix@^1.5.4": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.0.tgz#eb7536259ee695646e75c4c7b0c9a857ea174781" + integrity sha512-qwfpsHmFuhAS/dVd4uBIraMxRd56vwBUYQGZ6GpXnFuM2XMRFJbIyruFKKlW2daQliuYZwe0qfn/UjFCDKic5g== + "@types/prop-types@*", "@types/prop-types@^15.0.0": version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "6.9.8" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.8.tgz#f2a7de3c107b89b441e071d5472e6b726b4adf45" + integrity sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg== "@types/range-parser@*": version "1.2.4" @@ -2855,13 +2892,13 @@ integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== "@types/react-router-config@*", "@types/react-router-config@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" - integrity sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg== + version "5.0.7" + resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.7.tgz#36207a3fe08b271abee62b26993ee932d13cbb02" + integrity sha512-pFFVXUIydHlcJP6wJm7sDii5mD/bCmmAY0wQzq+M+uX7bqS95AQqHZWP1iNMKrWVQSuHIzj5qi9BvrtLX2/T4w== dependencies: "@types/history" "^4.7.11" "@types/react" "*" - "@types/react-router" "*" + "@types/react-router" "^5.1.0" "@types/react-router-dom@*": version "5.3.3" @@ -2872,7 +2909,7 @@ "@types/react" "*" "@types/react-router" "*" -"@types/react-router@*": +"@types/react-router@*", "@types/react-router@^5.1.0": version "5.1.20" resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c" integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q== @@ -2881,9 +2918,9 @@ "@types/react" "*" "@types/react@*": - version "18.0.18" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.18.tgz#9f16f33d57bc5d9dca848d12c3572110ff9429ac" - integrity sha512-6hI08umYs6NaiHFEEGioXnxJ+oEhY3eRz8VCUaudZmGdtvPviCJB8mgaMxaDWAdPSYd4eFavrPk2QIolwbLYrg== + version "18.2.21" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.21.tgz#774c37fd01b522d0b91aed04811b58e4e0514ed9" + integrity sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2902,9 +2939,17 @@ "@types/node" "*" "@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + version "0.16.3" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" + integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ== + +"@types/send@*": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" + integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== + dependencies: + "@types/mime" "^1" + "@types/node" "*" "@types/serve-index@^1.9.1": version "1.9.1" @@ -2914,10 +2959,11 @@ "@types/express" "*" "@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" - integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== + version "1.15.2" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.2.tgz#3e5419ecd1e40e7405d34093f10befb43f63381a" + integrity sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw== dependencies: + "@types/http-errors" "*" "@types/mime" "*" "@types/node" "*" @@ -2928,10 +2974,10 @@ dependencies: "@types/node" "*" -"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== +"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.8.tgz#bb197b9639aa1a04cf464a617fe800cccd92ad5c" + integrity sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw== "@types/websocket@1.0.2": version "1.0.2" @@ -2940,132 +2986,151 @@ dependencies: "@types/node" "*" -"@types/ws@^8.5.1": - version "8.5.3" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" - integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== +"@types/websocket@^1.0.3": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.6.tgz#ec8dce5915741632ac3a4b1f951b6d4156e32d03" + integrity sha512-JXkliwz93B2cMWOI1ukElQBPN88vMg3CruvW4KVSKpflt3NyNCJImnhIuB/f97rG7kakqRJGFiwkA895Kn02Dg== + dependencies: + "@types/node" "*" + +"@types/ws@^8.5.5": + version "8.5.5" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" + integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg== dependencies: "@types/node" "*" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.24" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" + integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== + dependencies: + "@types/yargs-parser" "*" + +"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" + integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" + integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" + integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" + integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-opt" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/wast-printer" "1.11.6" + +"@webassemblyjs/wasm-gen@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" + integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" + integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + +"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" + integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== + dependencies: + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" + integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== + dependencies: + "@webassemblyjs/ast" "1.11.6" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -3093,25 +3158,25 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== -acorn-walk@^8.0.0: +acorn-walk@^8.0.0, acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== +acorn@^8.0.4, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== address@^1.0.1, address@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/address/-/address-1.2.0.tgz#d352a62c92fee90f89a693eccd2a8b2139ab02d9" - integrity sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig== + version "1.2.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" + integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== aggregate-error@^3.0.0: version "3.1.0" @@ -3133,7 +3198,7 @@ ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: +ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== @@ -3150,10 +3215,10 @@ ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.8.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" - integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== +ajv@^8.0.0, ajv@^8.9.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -3161,31 +3226,31 @@ ajv@^8.0.0, ajv@^8.8.0: uri-js "^4.2.2" algoliasearch-helper@^3.10.0: - version "3.11.1" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.11.1.tgz#d83ab7f1a2a374440686ef7a144b3c288b01188a" - integrity sha512-mvsPN3eK4E0bZG0/WlWJjeqe/bUD2KOEVOl0GyL/TGXn6wcpZU8NOuztGHCUKXkyg5gq6YzUakVTmnmSSO5Yiw== + version "3.14.0" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.14.0.tgz#2409c2591952719ab6fba1de77b3bbe5094ab85e" + integrity sha512-gXDXzsSS0YANn5dHr71CUXOo84cN4azhHKUbg71vAWnH+1JBiR4jf7to3t3JHXknXkbV0F7f055vUSBKrltHLQ== dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0, algoliasearch@^4.13.1: - version "4.14.3" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.14.3.tgz#f02a77a4db17de2f676018938847494b692035e7" - integrity sha512-GZTEuxzfWbP/vr7ZJfGzIl8fOsoxN916Z6FY2Egc9q2TmZ6hvq5KfAxY89pPW01oW/2HDEKA8d30f9iAH9eXYg== - dependencies: - "@algolia/cache-browser-local-storage" "4.14.3" - "@algolia/cache-common" "4.14.3" - "@algolia/cache-in-memory" "4.14.3" - "@algolia/client-account" "4.14.3" - "@algolia/client-analytics" "4.14.3" - "@algolia/client-common" "4.14.3" - "@algolia/client-personalization" "4.14.3" - "@algolia/client-search" "4.14.3" - "@algolia/logger-common" "4.14.3" - "@algolia/logger-console" "4.14.3" - "@algolia/requester-browser-xhr" "4.14.3" - "@algolia/requester-common" "4.14.3" - "@algolia/requester-node-http" "4.14.3" - "@algolia/transporter" "4.14.3" +algoliasearch@^4.13.1, algoliasearch@^4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.19.1.tgz#18111fb422eaf841737adb92d5ab12133d244218" + integrity sha512-IJF5b93b2MgAzcE/tuzW0yOPnuUyRgGAtaPv5UUywXM8kzqfdwZTO4sPJBzoGz1eOy6H9uEchsJsBFTELZSu+g== + dependencies: + "@algolia/cache-browser-local-storage" "4.19.1" + "@algolia/cache-common" "4.19.1" + "@algolia/cache-in-memory" "4.19.1" + "@algolia/client-account" "4.19.1" + "@algolia/client-analytics" "4.19.1" + "@algolia/client-common" "4.19.1" + "@algolia/client-personalization" "4.19.1" + "@algolia/client-search" "4.19.1" + "@algolia/logger-common" "4.19.1" + "@algolia/logger-console" "4.19.1" + "@algolia/requester-browser-xhr" "4.19.1" + "@algolia/requester-common" "4.19.1" + "@algolia/requester-node-http" "4.19.1" + "@algolia/transporter" "4.19.1" ansi-align@^3.0.0, ansi-align@^3.0.1: version "3.0.1" @@ -3224,66 +3289,68 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: color-convert "^2.0.1" ansi-styles@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.0.tgz#87313c102b8118abd57371afab34618bf7350ed3" - integrity sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ== + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== antd@^5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/antd/-/antd-5.0.7.tgz#0c182ad33c9de81b204f4fa430d75480fad7e0d6" - integrity sha512-A/HO/VCS6nHMkpnjfPSxXoet1MBu6N003osaGbSI3mnOvRj0V/9jEOXJ2slj+2YNhACFYJfVyXeEamwQx2Njcw== - dependencies: - "@ant-design/colors" "^6.0.0" - "@ant-design/cssinjs" "^1.0.0" - "@ant-design/icons" "^4.7.0" - "@ant-design/react-slick" "~0.29.1" + version "5.8.5" + resolved "https://registry.yarnpkg.com/antd/-/antd-5.8.5.tgz#36574f6d4e90c683c9a77f7797416ac180035055" + integrity sha512-CaCl0BquElbSmilzKunyf22hVhgErKjzh2twQ+ZuFUSZfTOibi6/bwXp93lnT/VGgnc3Z3f2OizybzXWR7/tQg== + dependencies: + "@ant-design/colors" "^7.0.0" + "@ant-design/cssinjs" "^1.16.0" + "@ant-design/icons" "^5.2.2" + "@ant-design/react-slick" "~1.0.0" "@babel/runtime" "^7.18.3" - "@ctrl/tinycolor" "^3.4.0" - "@rc-component/tour" "~1.0.1-2" + "@ctrl/tinycolor" "^3.6.0" + "@rc-component/color-picker" "~1.4.0" + "@rc-component/mutate-observer" "^1.0.0" + "@rc-component/tour" "~1.8.1" + "@rc-component/trigger" "^1.15.0" classnames "^2.2.6" copy-to-clipboard "^3.2.0" dayjs "^1.11.1" - lodash "^4.17.21" - rc-cascader "~3.7.0" - rc-checkbox "~2.3.0" - rc-collapse "~3.4.2" - rc-dialog "~9.0.2" - rc-drawer "~6.0.0" - rc-dropdown "~4.0.0" - rc-field-form "~1.27.0" - rc-image "~5.12.0" - rc-input "~0.1.4" - rc-input-number "~7.4.0" - rc-mentions "~1.13.1" - rc-menu "~9.8.0" - rc-motion "^2.6.1" - rc-notification "~5.0.0-alpha.9" - rc-pagination "~3.2.0" - rc-picker "~3.1.1" + qrcode.react "^3.1.0" + rc-cascader "~3.14.0" + rc-checkbox "~3.1.0" + rc-collapse "~3.7.0" + rc-dialog "~9.1.0" + rc-drawer "~6.2.0" + rc-dropdown "~4.1.0" + rc-field-form "~1.36.0" + rc-image "~7.1.0" + rc-input "~1.1.0" + rc-input-number "~8.0.2" + rc-mentions "~2.5.0" + rc-menu "~9.10.0" + rc-motion "^2.7.3" + rc-notification "~5.0.4" + rc-pagination "~3.6.0" + rc-picker "~3.13.0" rc-progress "~3.4.1" - rc-rate "~2.9.0" + rc-rate "~2.12.0" rc-resize-observer "^1.2.0" - rc-segmented "~2.1.0" - rc-select "~14.1.13" - rc-slider "~10.0.0" - rc-steps "~6.0.0-alpha.2" - rc-switch "~4.0.0" - rc-table "~7.26.0" - rc-tabs "~12.4.2" - rc-textarea "~0.4.5" - rc-tooltip "~5.2.0" - rc-tree "~5.7.0" - rc-tree-select "~5.5.4" - rc-trigger "^5.2.10" + rc-segmented "~2.2.0" + rc-select "~14.7.1" + rc-slider "~10.1.0" + rc-steps "~6.0.1" + rc-switch "~4.1.0" + rc-table "~7.32.1" + rc-tabs "~12.9.0" + rc-textarea "~1.3.3" + rc-tooltip "~6.0.0" + rc-tree "~5.7.6" + rc-tree-select "~5.11.0" rc-upload "~4.3.0" - rc-util "^5.25.2" + rc-util "^5.37.0" scroll-into-view-if-needed "^3.0.3" - shallowequal "^1.1.0" + throttle-debounce "^5.0.0" anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -3347,6 +3414,11 @@ async-validator@^4.1.0: resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339" integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== +async@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -3358,12 +3430,12 @@ at-least-node@^1.0.0: integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== autoprefixer@^10.4.12, autoprefixer@^10.4.7: - version "10.4.13" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" - integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== + version "10.4.15" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.15.tgz#a1230f4aeb3636b89120b34a1f513e2f6834d530" + integrity sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew== dependencies: - browserslist "^4.21.4" - caniuse-lite "^1.0.30001426" + browserslist "^4.21.10" + caniuse-lite "^1.0.30001520" fraction.js "^4.2.0" normalize-range "^0.1.2" picocolors "^1.0.0" @@ -3377,9 +3449,9 @@ axios@^0.25.0: follow-redirects "^1.14.7" babel-loader@^8.2.5: - version "8.2.5" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" - integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== + version "8.3.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" + integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== dependencies: find-cache-dir "^3.3.1" loader-utils "^2.0.0" @@ -3408,37 +3480,29 @@ babel-plugin-extract-import-names@1.6.22: dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-polyfill-corejs2@^0.3.2, babel-plugin-polyfill-corejs2@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" - integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== - dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.3.3" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz#d7e09c9a899079d71a8b670c6181af56ec19c5c7" - integrity sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw== +babel-plugin-polyfill-corejs2@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz#8097b4cb4af5b64a1d11332b6fb72ef5e64a054c" + integrity sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.2" - core-js-compat "^3.21.0" + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.4.2" + semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" - integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== +babel-plugin-polyfill-corejs3@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz#b4f719d0ad9bb8e0c23e3e630c0c8ec6dd7a1c52" + integrity sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - core-js-compat "^3.25.1" + "@babel/helper-define-polyfill-provider" "^0.4.2" + core-js-compat "^3.31.0" -babel-plugin-polyfill-regenerator@^0.4.0, babel-plugin-polyfill-regenerator@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" - integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== +babel-plugin-polyfill-regenerator@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz#80d0f3e1098c080c8b5a65f41e9427af692dc326" + integrity sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" + "@babel/helper-define-polyfill-provider" "^0.4.2" backo2@^1.0.2: version "1.0.2" @@ -3476,9 +3540,9 @@ batch@0.6.1: integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== + version "2.2.3" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" + integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== big.js@^5.2.2: version "5.2.2" @@ -3499,10 +3563,10 @@ bl@^4.0.3: inherits "^2.0.4" readable-stream "^3.4.0" -body-parser@1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" - integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== dependencies: bytes "3.1.2" content-type "~1.0.4" @@ -3512,15 +3576,15 @@ body-parser@1.20.0: http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.10.3" + qs "6.11.0" raw-body "2.5.1" type-is "~1.6.18" unpipe "1.0.0" bonjour-service@^1.0.11: - version "1.0.14" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.14.tgz#c346f5bc84e87802d08f8d5a60b93f758e514ee7" - integrity sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" + integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== dependencies: array-flatten "^2.1.2" dns-equal "^1.0.0" @@ -3580,15 +3644,15 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.21.3, browserslist@^4.21.4: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.21.9: + version "4.21.10" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0" + integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" + caniuse-lite "^1.0.30001517" + electron-to-chromium "^1.4.477" + node-releases "^2.0.13" + update-browserslist-db "^1.0.11" buffer-from@^1.0.0: version "1.1.2" @@ -3603,6 +3667,13 @@ buffer@^5.5.0, buffer@^5.7.0: base64-js "^1.3.1" ieee754 "^1.1.13" +bufferutil@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -3653,9 +3724,9 @@ camelcase-css@2.0.1: integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-api@^3.0.0: version "3.0.0" @@ -3667,10 +3738,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: - version "1.0.30001441" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz#987437b266260b640a23cd18fbddb509d7f69f3e" - integrity sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001520: + version "1.0.30001525" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz#d2e8fdec6116ffa36284ca2c33ef6d53612fe1c8" + integrity sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q== ccount@^1.0.0: version "1.1.0" @@ -3682,7 +3753,7 @@ ccount@^2.0.0: resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== -chalk@^2.0.0: +chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3691,7 +3762,7 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3699,6 +3770,11 @@ chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + character-entities-legacy@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" @@ -3731,7 +3807,7 @@ cheerio-select@^2.1.0: domhandler "^5.0.3" domutils "^3.0.1" -cheerio@^1.0.0-rc.12: +cheerio@^1.0.0-rc.10, cheerio@^1.0.0-rc.12: version "1.0.0-rc.12" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== @@ -3774,20 +3850,20 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.3.1, classnames@^2.3.2: +ci-info@^3.2.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== + +classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1, classnames@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== -classnames@^2.2.6: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== - clean-css@^5.2.2, clean-css@^5.3.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.1.tgz#d0610b0b90d125196a2894d35366f734e5d7aa32" - integrity sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg== + version "5.3.2" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.2.tgz#70ecc7d4d4114921f5d298349ff86a31a9975224" + integrity sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww== dependencies: source-map "~0.6.0" @@ -3807,9 +3883,9 @@ cli-boxes@^3.0.0: integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== cli-table3@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a" - integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw== + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== dependencies: string-width "^4.2.0" optionalDependencies: @@ -3830,9 +3906,9 @@ clone-deep@^4.0.1: shallow-clone "^3.0.0" clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== dependencies: mimic-response "^1.0.0" @@ -3892,14 +3968,14 @@ colord@^2.9.1: integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== colorette@^2.0.10: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== combine-promises@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71" - integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.2.0.tgz#5f2e68451862acf85761ded4d9e2af7769c2ca6a" + integrity sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ== combined-stream@^1.0.8: version "1.0.8" @@ -3918,6 +3994,11 @@ comma-separated-tokens@^2.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3963,10 +4044,10 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" -compute-scroll-into-view@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-2.0.2.tgz#ac5cc71ca833884866e581a82d8558a6ed7ee877" - integrity sha512-W+4Iti92hktsTtNPNeRM1vE0JdqCBk5qIabRafpr5pGrQhQ+xzCv0NGnFzTCKmW4yGLm9Aovbw8YNxloe2z9tQ== +compute-scroll-into-view@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz#c418900a5c56e2b04b885b54995df164535962b1" + integrity sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A== concat-map@0.0.1: version "0.0.1" @@ -4013,16 +4094,14 @@ content-disposition@0.5.4: safe-buffer "5.2.1" content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== cookie-signature@1.0.6: version "1.0.6" @@ -4035,9 +4114,9 @@ cookie@0.5.0: integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== copy-text-to-clipboard@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" - integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz#0202b2d9bdae30a49a53f898626dcc3b49ad960b" + integrity sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q== copy-to-clipboard@^3.2.0: version "3.3.3" @@ -4058,22 +4137,22 @@ copy-webpack-plugin@^11.0.0: schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.21.0, core-js-compat@^3.25.1: - version "3.27.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.27.0.tgz#e2c58a89df6432a5f36f3fa34097e9e83e709fb6" - integrity sha512-spN2H4E/wocMML7XtbKuqttHHM+zbF3bAdl9mT4/iyFaF33bowQGjxiWNWyvUJGH9F+hTgnhWziiLtwu3oC/Qg== +core-js-compat@^3.31.0: + version "3.32.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.1.tgz#55f9a7d297c0761a8eb1d31b593e0f5b6ffae964" + integrity sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA== dependencies: - browserslist "^4.21.4" + browserslist "^4.21.10" -core-js-pure@^3.20.2: - version "3.25.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.0.tgz#f8d1f176ff29abbfeb610110de891d5ae5a361d4" - integrity sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A== +core-js-pure@^3.30.2: + version "3.32.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.1.tgz#5775b88f9062885f67b6d7edce59984e89d276f3" + integrity sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ== core-js@^3.23.3: - version "3.25.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.0.tgz#be71d9e0dd648ffd70c44a7ec2319d039357eceb" - integrity sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA== + version "3.32.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.1.tgz#a7d8736a3ed9dd05940c3c4ff32c591bb735be77" + integrity sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ== core-util-is@~1.0.0: version "1.0.3" @@ -4091,10 +4170,10 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== +cosmiconfig@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" import-fresh "^3.2.1" @@ -4102,6 +4181,16 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +cosmiconfig@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.2.0.tgz#f7d17c56a590856cd1e7cee98734dca272b0d8fd" + integrity sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ== + dependencies: + import-fresh "^3.2.1" + js-yaml "^4.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -4115,11 +4204,11 @@ cross-fetch@3.1.4: node-fetch "2.6.1" cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== dependencies: - node-fetch "2.6.7" + node-fetch "^2.6.12" cross-spawn@^7.0.3: version "7.0.3" @@ -4136,46 +4225,46 @@ crypto-random-string@^2.0.0: integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== css-declaration-sorter@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" - integrity sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w== + version "6.4.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" + integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== css-loader@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.1.tgz#e98106f154f6e1baf3fc3bc455cb9981c1d5fd2e" - integrity sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw== + version "6.8.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88" + integrity sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g== dependencies: icss-utils "^5.1.0" - postcss "^8.4.7" + postcss "^8.4.21" postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" + postcss-modules-local-by-default "^4.0.3" postcss-modules-scope "^3.0.0" postcss-modules-values "^4.0.0" postcss-value-parser "^4.2.0" - semver "^7.3.5" + semver "^7.3.8" css-minimizer-webpack-plugin@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.0.0.tgz#e11800388c19c2b7442c39cc78ac8ae3675c9605" - integrity sha512-7ZXXRzRHvofv3Uac5Y+RkWRNo0ZMlcg8e9/OtrqUYmwDWJo+qs67GvdeFrXLsFb7czKNwjQhPkM0avlIYl+1nA== + version "4.2.2" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz#79f6199eb5adf1ff7ba57f105e3752d15211eb35" + integrity sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA== dependencies: cssnano "^5.1.8" - jest-worker "^27.5.1" - postcss "^8.4.13" + jest-worker "^29.1.2" + postcss "^8.4.17" schema-utils "^4.0.0" serialize-javascript "^6.0.0" source-map "^0.6.1" css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== dependencies: boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" css-select@^5.1.0: version "5.1.0" @@ -4196,12 +4285,7 @@ css-tree@^1.1.2, css-tree@^1.1.3: mdn-data "2.0.14" source-map "^0.6.1" -css-what@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== - -css-what@^6.1.0: +css-what@^6.0.1, css-what@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== @@ -4212,33 +4296,33 @@ cssesc@^3.0.0: integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== cssnano-preset-advanced@^5.3.8: - version "5.3.9" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.9.tgz#99e1cdf81a467a5e6c366cfc6d874a166c4d9a67" - integrity sha512-njnh4pp1xCsibJcEHnWZb4EEzni0ePMqPuPNyuWT4Z+YeXmsgqNuTPIljXFEXhxGsWs9183JkXgHxc1TcsahIg== + version "5.3.10" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz#25558a1fbf3a871fb6429ce71e41be7f5aca6eef" + integrity sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ== dependencies: autoprefixer "^10.4.12" - cssnano-preset-default "^5.2.13" + cssnano-preset-default "^5.2.14" postcss-discard-unused "^5.1.0" postcss-merge-idents "^5.1.1" postcss-reduce-idents "^5.2.0" postcss-zindex "^5.1.0" -cssnano-preset-default@^5.2.12, cssnano-preset-default@^5.2.13: - version "5.2.13" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz#e7353b0c57975d1bdd97ac96e68e5c1b8c68e990" - integrity sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ== +cssnano-preset-default@^5.2.14: + version "5.2.14" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz#309def4f7b7e16d71ab2438052093330d9ab45d8" + integrity sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A== dependencies: css-declaration-sorter "^6.3.1" cssnano-utils "^3.1.0" postcss-calc "^8.2.3" - postcss-colormin "^5.3.0" + postcss-colormin "^5.3.1" postcss-convert-values "^5.1.3" postcss-discard-comments "^5.1.2" postcss-discard-duplicates "^5.1.0" postcss-discard-empty "^5.1.1" postcss-discard-overridden "^5.1.0" postcss-merge-longhand "^5.1.7" - postcss-merge-rules "^5.1.3" + postcss-merge-rules "^5.1.4" postcss-minify-font-values "^5.1.0" postcss-minify-gradients "^5.1.1" postcss-minify-params "^5.1.4" @@ -4253,7 +4337,7 @@ cssnano-preset-default@^5.2.12, cssnano-preset-default@^5.2.13: postcss-normalize-url "^5.1.0" postcss-normalize-whitespace "^5.1.1" postcss-ordered-values "^5.1.3" - postcss-reduce-initial "^5.1.1" + postcss-reduce-initial "^5.1.2" postcss-reduce-transforms "^5.1.0" postcss-svgo "^5.1.0" postcss-unique-selectors "^5.1.1" @@ -4264,11 +4348,11 @@ cssnano-utils@^3.1.0: integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== cssnano@^5.1.12, cssnano@^5.1.8: - version "5.1.13" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.13.tgz#83d0926e72955332dc4802a7070296e6258efc0a" - integrity sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ== + version "5.1.15" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf" + integrity sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw== dependencies: - cssnano-preset-default "^5.2.12" + cssnano-preset-default "^5.2.14" lilconfig "^2.0.3" yaml "^1.10.2" @@ -4279,15 +4363,18 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" -csstype@^3.0.10: - version "3.1.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== +csstype@^3.0.10, csstype@^3.0.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== -csstype@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" - integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" dataloader@2.0.0: version "2.0.0" @@ -4295,30 +4382,30 @@ dataloader@2.0.0: integrity sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ== dayjs@^1.11.1: - version "1.11.7" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2" - integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ== + version "1.11.9" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a" + integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA== -debug@2.6.9, debug@^2.6.0: +debug@2.6.9, debug@^2.2.0, debug@^2.6.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@^4.0.0: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^4.1.0, debug@^4.1.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== +debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: - ms "2.1.2" + ms "^2.1.1" decode-named-character-reference@^1.0.0: version "1.0.2" @@ -4347,9 +4434,9 @@ deep-extend@^0.6.0: integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== default-gateway@^6.0.3: version "6.0.3" @@ -4369,9 +4456,9 @@ define-lazy-prop@^2.0.0: integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -4428,9 +4515,9 @@ detab@2.0.4: repeat-string "^1.5.4" detect-libc@^2.0.0, detect-libc@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" - integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== + version "2.0.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" + integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== detect-node-es@^1.1.0: version "1.1.0" @@ -4451,12 +4538,12 @@ detect-port-alt@^1.1.6: debug "^2.6.0" detect-port@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" - integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== + version "1.5.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" + integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== dependencies: address "^1.0.1" - debug "^2.6.0" + debug "4" diff@^4.0.1: version "4.0.2" @@ -4481,9 +4568,9 @@ dns-equal@^1.0.0: integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== dns-packet@^5.2.2: - version "5.4.0" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" - integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== dependencies: "@leichtgewicht/ip-codec" "^2.0.1" @@ -4504,9 +4591,9 @@ docusaurus-graphql-plugin@0.5.0: url-join "^4.0.1" docusaurus-plugin-sass@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.2.tgz#9b7f8c6fbe833677064ec05b09b98d90b50be324" - integrity sha512-ZZBpj3PrhGpYE2kAnkZB9NRwy/CDi4rGun1oec6PYR8YvGzqxYGtXvLgHi6FFbu8/N483klk8udqyYMh6Ted+A== + version "0.2.5" + resolved "https://registry.yarnpkg.com/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.5.tgz#6bfb8a227ac6265be685dcbc24ba1989e27b8005" + integrity sha512-Z+D0fLFUKcFpM+bqSUmqKIU+vO+YF1xoEQh5hoFreg2eMf722+siwXDD+sqtwU8E4MvVpuvsQfaHwODNlxJAEg== dependencies: sass-loader "^10.1.1" @@ -4523,9 +4610,9 @@ dom-converter@^0.2.0: utila "~0.4" dom-serializer@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== dependencies: domelementtype "^2.0.1" domhandler "^4.2.0" @@ -4545,21 +4632,21 @@ domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== -domhandler@^4.0.0, domhandler@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" - integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== dependencies: domelementtype "^2.2.0" -domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: +domhandler@^5.0.2, domhandler@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== dependencies: domelementtype "^2.3.0" -domutils@^2.5.2, domutils@^2.6.0: +domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -4569,13 +4656,13 @@ domutils@^2.5.2, domutils@^2.6.0: domhandler "^4.2.0" domutils@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" - integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" - domhandler "^5.0.1" + domhandler "^5.0.3" dot-case@^3.0.4: version "3.0.4" @@ -4593,14 +4680,14 @@ dot-prop@^5.2.0: is-obj "^2.0.0" dotenv@^16.0.1: - version "16.0.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d" - integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== duplexer@^0.1.2: version "0.1.2" @@ -4617,10 +4704,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.251: - version "1.4.284" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== +electron-to-chromium@^1.4.477: + version "1.4.508" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96" + integrity sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg== emoji-regex@^8.0.0: version "8.0.0" @@ -4654,10 +4741,10 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.10.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== +enhanced-resolve@^5.15.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -4667,10 +4754,10 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" - integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== error-ex@^1.3.1: version "1.3.2" @@ -4679,10 +4766,36 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f" + integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA== + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" escalade@^3.1.1: version "3.1.1" @@ -4740,24 +4853,19 @@ estraverse@^4.1.1: integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -eta@^1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" - integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== - eta@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eta/-/eta-2.0.0.tgz#376865fadebc899e5b6dfce82fae64cbbe47e594" - integrity sha512-NqE7S2VmVwgMS8yBxsH4VgNQjNjLq1gfGU0u9I6Cjh468nPRMoDfGdK9n1p/3Dvsw3ebklDkZsFAnKJ9sefjBA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/eta/-/eta-2.2.0.tgz#eb8b5f8c4e8b6306561a455e62cd7492fe3a9b8a" + integrity sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g== etag@~1.8.1: version "1.8.1" @@ -4813,13 +4921,13 @@ expand-template@^2.0.3: integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== express@^4.17.3: - version "4.18.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" - integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.0" + body-parser "1.20.1" content-disposition "0.5.4" content-type "~1.0.4" cookie "0.5.0" @@ -4838,7 +4946,7 @@ express@^4.17.3: parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.10.3" + qs "6.11.0" range-parser "~1.2.1" safe-buffer "5.2.1" send "0.18.0" @@ -4849,6 +4957,13 @@ express@^4.17.3: utils-merge "1.0.1" vary "~1.1.2" +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -4871,10 +4986,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.11, fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== +fast-glob@^3.1.1, fast-glob@^3.2.11, fast-glob@^3.2.9, fast-glob@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4895,9 +5010,9 @@ fast-url-parser@1.1.3: punycode "^1.3.2" fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" @@ -4921,9 +5036,9 @@ fbjs-css-vars@^1.0.0: integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" - integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== + version "3.0.5" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.5.tgz#aa0edb7d5caa6340011790bd9249dbef8a81128d" + integrity sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg== dependencies: cross-fetch "^3.1.5" fbjs-css-vars "^1.0.0" @@ -4931,7 +5046,7 @@ fbjs@^3.0.0, fbjs@^3.0.1: object-assign "^4.1.0" promise "^7.1.1" setimmediate "^1.0.5" - ua-parser-js "^0.7.30" + ua-parser-js "^1.0.35" feed@^4.2.2: version "4.2.2" @@ -5006,22 +5121,22 @@ find-up@^5.0.0: path-exists "^4.0.0" flux@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" - integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== + version "4.0.4" + resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.4.tgz#9661182ea81d161ee1a6a6af10d20485ef2ac572" + integrity sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw== dependencies: fbemitter "^3.0.0" fbjs "^3.0.1" follow-redirects@^1.0.0, follow-redirects@^1.14.7: - version "1.15.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" - integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" - integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== + version "6.5.3" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz#eda2eff6e22476a2688d10661688c47f611b37f3" + integrity sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" @@ -5052,9 +5167,9 @@ forwarded@0.2.0: integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fraction.js@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" - integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== + version "4.3.4" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.4.tgz#b2bac8249a610c3396106da97c5a71da75b94b1c" + integrity sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q== fresh@0.5.2: version "0.5.2" @@ -5085,10 +5200,10 @@ fs-extra@^9.0.0, fs-extra@^9.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-monkey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== +fs-monkey@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.4.tgz#ee8c1b53d3fe8bb7e5d2c5c5dfc0168afdd2f747" + integrity sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ== fs.realpath@^1.0.0: version "1.0.0" @@ -5096,9 +5211,9 @@ fs.realpath@^1.0.0: integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.1: version "1.1.1" @@ -5111,13 +5226,14 @@ gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" + has-proto "^1.0.1" + has-symbols "^1.0.3" get-nonce@^1.0.0: version "1.0.1" @@ -5190,9 +5306,9 @@ glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: path-is-absolute "^1.0.0" global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" + integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== dependencies: ini "2.0.0" @@ -5242,13 +5358,13 @@ globby@^11.0.1, globby@^11.0.4, globby@^11.1.0: slash "^3.0.0" globby@^13.1.1: - version "13.1.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515" - integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ== + version "13.2.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" + integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== dependencies: dir-glob "^3.0.1" - fast-glob "^3.2.11" - ignore "^5.2.0" + fast-glob "^3.3.0" + ignore "^5.2.4" merge2 "^1.4.1" slash "^4.0.0" @@ -5270,9 +5386,9 @@ got@^9.6.0: url-parse-lax "^3.0.0" graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphql-ws@^4.4.1: version "4.9.0" @@ -5280,9 +5396,9 @@ graphql-ws@^4.4.1: integrity sha512-sHkK9+lUm20/BGawNEWNtVAeJzhZeBg21VmvmLoT5NdGVeZWv5PdIhkcayQIAgjSyyQ17WMKmbDijIPG2On+Ag== graphql@^15.5.0: - version "15.6.1" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.6.1.tgz#9125bdf057553525da251e19e96dab3d3855ddfc" - integrity sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw== + version "15.8.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" + integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== gray-matter@^4.0.3: version "4.0.3" @@ -5323,7 +5439,12 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" -has-symbols@^1.0.1, has-symbols@^1.0.3: +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -5448,9 +5569,16 @@ hpack.js@^2.1.6: wbuf "^1.1.0" html-entities@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" - integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" + integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== + +html-link-extractor@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/html-link-extractor/-/html-link-extractor-1.0.5.tgz#a4be345cb13b8c3352d82b28c8b124bb7bf5dd6f" + integrity sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw== + dependencies: + cheerio "^1.0.0-rc.10" html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: version "6.1.0" @@ -5466,9 +5594,9 @@ html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: terser "^5.10.0" html-tags@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" - integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== + version "3.3.1" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" + integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== html-void-elements@^1.0.0: version "1.0.5" @@ -5476,9 +5604,9 @@ html-void-elements@^1.0.0: integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== html-webpack-plugin@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + version "5.5.3" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz#72270f4a78e222b5825b296e5e3e1328ad525a3e" + integrity sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg== dependencies: "@types/html-minifier-terser" "^6.0.0" html-minifier-terser "^6.0.2" @@ -5497,14 +5625,14 @@ htmlparser2@^6.1.0: entities "^2.0.0" htmlparser2@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" - integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== dependencies: domelementtype "^2.3.0" - domhandler "^5.0.2" + domhandler "^5.0.3" domutils "^3.0.1" - entities "^4.3.0" + entities "^4.4.0" http-cache-semantics@^4.0.0: version "4.1.1" @@ -5538,9 +5666,9 @@ http-errors@~1.6.2: statuses ">= 1.4.0 < 2" http-parser-js@>=0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== http-proxy-middleware@^2.0.3: version "2.0.6" @@ -5574,6 +5702,13 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-utils@^5.0.0, icss-utils@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" @@ -5584,10 +5719,10 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.1.4, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +ignore@^5.1.4, ignore@^5.2.0, ignore@^5.2.4: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== image-size@^1.0.1: version "1.0.2" @@ -5597,9 +5732,14 @@ image-size@^1.0.1: queue "6.0.2" immer@^9.0.7: - version "9.0.15" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" - integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ== + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== + +immutable@^4.0.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" + integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -5631,10 +5771,10 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -infima@0.2.0-alpha.42: - version "0.2.0-alpha.42" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.42.tgz#f6e86a655ad40877c6b4d11b2ede681eb5470aa5" - integrity sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww== +infima@0.2.0-alpha.43: + version "0.2.0-alpha.43" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.43.tgz#f7aa1d7b30b6c08afef441c726bac6150228cbe0" + integrity sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ== inflight@^1.0.4: version "1.0.6" @@ -5687,9 +5827,14 @@ ipaddr.js@1.9.1: integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + version "2.1.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" + integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== + +is-absolute-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-4.0.1.tgz#16e4d487d4fded05cfe0685e53ec86804a5e94dc" + integrity sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A== is-alphabetical@1.0.4, is-alphabetical@^1.0.0: version "1.0.4" @@ -5733,10 +5878,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.2.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" @@ -5859,6 +6004,13 @@ is-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== +is-relative-url@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-relative-url/-/is-relative-url-4.0.0.tgz#4d8371999ff6033b76e4d9972fb5bf496fddfa97" + integrity sha512-PkzoL1qKAYXNFct5IKdKRH/iBQou/oCC85QhXj6WKtUQBliZ4Yfd3Zk27RHu9KQG8r6zgvAA2AQKC9p+rqTszg== + dependencies: + is-absolute-url "^4.0.1" + is-root@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" @@ -5906,6 +6058,13 @@ isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isemail@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c" + integrity sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg== + dependencies: + punycode "2.x.x" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -5926,7 +6085,19 @@ iterall@^1.2.1: resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== -jest-worker@^27.4.5, jest-worker@^27.5.1: +jest-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.3.tgz#e15c3eac8716440d1ed076f09bc63ace1aebca63" + integrity sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== @@ -5935,15 +6106,30 @@ jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.1.2: + version "29.6.4" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.4.tgz#f34279f4afc33c872b470d4af21b281ac616abd3" + integrity sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q== + dependencies: + "@types/node" "*" + jest-util "^29.6.3" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jiti@^1.18.2: + version "1.19.3" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.3.tgz#ef554f76465b3c2b222dc077834a71f0d4a37569" + integrity sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w== + joi@^17.4.0, joi@^17.6.0: - version "17.6.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.6.0.tgz#0bb54f2f006c09a96e75ce687957bd04290054b2" - integrity sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw== + version "17.10.1" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.10.1.tgz#f908ee1617137cca5d83b91587cde80e472b5753" + integrity sha512-vIiDxQKmRidUVp8KngT8MZSOcmRVm2zV7jbMjNYWuHcJWI0bUck3nRTGQjhpPlQenIQIBC5Vp9AhcnHbWQqafw== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" "@sideway/address" "^4.1.3" - "@sideway/formula" "^3.0.0" + "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: @@ -6003,7 +6189,7 @@ json2mq@^0.2.0: dependencies: string-convert "^0.2.0" -json5@^2.1.2, json5@^2.2.1: +json5@^2.1.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -6039,10 +6225,10 @@ kleur@^4.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== -klona@^2.0.4, klona@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== +klona@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" + integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== latest-version@^5.1.0: version "5.1.0" @@ -6051,25 +6237,43 @@ latest-version@^5.1.0: dependencies: package-json "^6.3.0" +launch-editor@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" + integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.7.3" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== lilconfig@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.3.tgz#68f3005e921dafbd2a2afb48379986aa6d2579fd" - integrity sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha512-8ZmlJFVK9iCmtLz19HpSsR8HaAMWBT284VMNednLwlIMDP2hJDCIhUp0IZ2xUcZ+Ob6BM0VvCSJwzASDM45NLQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +link-check@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/link-check/-/link-check-5.2.0.tgz#595a339d305900bed8c1302f4342a29c366bf478" + integrity sha512-xRbhYLaGDw7eRDTibTAcl6fXtmUQ13vkezQiTqshHHdGueQeumgxxmQMIOmJYsh2p8BF08t8thhDQ++EAOOq3w== + dependencies: + is-relative-url "^4.0.0" + isemail "^3.2.0" + ms "^2.1.3" + needle "^3.1.0" loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== loader-utils@^2.0.0: version "2.0.4" @@ -6107,6 +6311,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + lodash.curry@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" @@ -6117,22 +6326,47 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.escape@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" + integrity sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw== + +lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== + lodash.flow@^3.3.0: version "3.5.0" resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== +lodash.invokemap@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.invokemap/-/lodash.invokemap-4.6.0.tgz#1748cda5d8b0ef8369c4eb3ec54c21feba1f2d62" + integrity sha512-CfkycNtMqgUlfjfdh2BhKO/ZXrP8ePOX5lEU/g0R3ItJcnuxWDwokMGKx1hWcfOikmyOVx6X9IwWnDGlgKl61w== + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== +lodash.pullall@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.pullall/-/lodash.pullall-4.2.0.tgz#9d98b8518b7c965b0fae4099bd9fb7df8bbf38ba" + integrity sha512-VhqxBKH0ZxPpLhiu68YD1KnHmbhQJQctcipvmFnqIBDYzcIHzf3Zpu0tpeOKtR4x76p9yohc506eGdOjTmyIBg== + lodash.uniq@4.5.0, lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@4.17.21, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: +lodash.uniqby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" + integrity sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww== + +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6197,6 +6431,28 @@ markdown-escapes@^1.0.0: resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== +markdown-link-check@^3.11.2: + version "3.11.2" + resolved "https://registry.yarnpkg.com/markdown-link-check/-/markdown-link-check-3.11.2.tgz#303a8a03d4a34c42ef3158e0b245bced26b5d904" + integrity sha512-zave+vI4AMeLp0FlUllAwGbNytSKsS3R2Zgtf3ufVT892Z/L6Ro9osZwE9PNA7s0IkJ4onnuHqatpsaCiAShJw== + dependencies: + async "^3.2.4" + chalk "^5.2.0" + commander "^10.0.1" + link-check "^5.2.0" + lodash "^4.17.21" + markdown-link-extractor "^3.1.0" + needle "^3.2.0" + progress "^2.0.3" + +markdown-link-extractor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/markdown-link-extractor/-/markdown-link-extractor-3.1.0.tgz#0d5a703630d791a9e2017449e1a9b294f2d2b676" + integrity sha512-r0NEbP1dsM+IqB62Ru9TXLP/HDaTdBNIeylYXumuBi6Xv4ufjE1/g3TnslYL8VNqNcGAGbMptQFHrrdfoZ/Sug== + dependencies: + html-link-extractor "^1.0.5" + marked "^4.1.0" + markdown-table@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" @@ -6207,6 +6463,11 @@ marked@^2.0.3: resolved "https://registry.yarnpkg.com/marked/-/marked-2.1.3.tgz#bd017cef6431724fd4b27e0657f5ceb14bff3753" integrity sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA== +marked@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + markprompt@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/markprompt/-/markprompt-0.1.7.tgz#fa049e11109d93372c45c38b3ca40bd5fdf751ea" @@ -6251,9 +6512,9 @@ mdast-util-find-and-replace@^2.0.0: unist-util-visit-parents "^5.0.0" mdast-util-from-markdown@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.0.tgz#0214124154f26154a2b3f9d401155509be45e894" - integrity sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g== + version "1.3.1" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" + integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww== dependencies: "@types/mdast" "^3.0.0" "@types/unist" "^2.0.0" @@ -6404,11 +6665,11 @@ media-typer@0.3.0: integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memfs@^3.1.2, memfs@^3.4.3: - version "3.4.7" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.7.tgz#e5252ad2242a724f938cb937e3c4f7ceb1f70e5a" - integrity sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: - fs-monkey "^1.0.3" + fs-monkey "^1.0.4" merge-descriptors@1.0.1: version "1.0.1" @@ -6436,9 +6697,9 @@ methods@~1.1.2: integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad" - integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8" + integrity sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw== dependencies: decode-named-character-reference "^1.0.0" micromark-factory-destination "^1.0.0" @@ -6458,20 +6719,19 @@ micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: uvu "^0.5.0" micromark-extension-gfm-autolink-literal@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz#dc589f9c37eaff31a175bab49f12290edcf96058" - integrity sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg== + version "1.0.5" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz#5853f0e579bbd8ef9e39a7c0f0f27c5a063a66e7" + integrity sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg== dependencies: micromark-util-character "^1.0.0" micromark-util-sanitize-uri "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" - uvu "^0.5.0" micromark-extension-gfm-footnote@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.0.tgz#73e3db823db9defef25f68074cb4cf4bb9cf6a8c" - integrity sha512-RWYce7j8+c0n7Djzv5NzGEGitNNYO3uj+h/XYMdS/JinH1Go+/Qkomg/rfxExFzYTiydaV6GLeffGO5qcJbMPA== + version "1.1.2" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz#05e13034d68f95ca53c99679040bc88a6f92fe2e" + integrity sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q== dependencies: micromark-core-commonmark "^1.0.0" micromark-factory-space "^1.0.0" @@ -6483,9 +6743,9 @@ micromark-extension-gfm-footnote@^1.0.0: uvu "^0.5.0" micromark-extension-gfm-strikethrough@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.5.tgz#4db40b87d674a6fe1d00d59ac91118e4f5960f12" - integrity sha512-X0oI5eYYQVARhiNfbETy7BfLSmSilzN1eOuoRnrf9oUNsPRrWOAe9UqSizgw1vNxQBfOwL+n2610S3bYjVNi7w== + version "1.0.7" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz#c8212c9a616fa3bf47cb5c711da77f4fdc2f80af" + integrity sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw== dependencies: micromark-util-chunked "^1.0.0" micromark-util-classify-character "^1.0.0" @@ -6495,9 +6755,9 @@ micromark-extension-gfm-strikethrough@^1.0.0: uvu "^0.5.0" micromark-extension-gfm-table@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.5.tgz#7b708b728f8dc4d95d486b9e7a2262f9cddbcbb4" - integrity sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg== + version "1.0.7" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz#dcb46074b0c6254c3fc9cc1f6f5002c162968008" + integrity sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw== dependencies: micromark-factory-space "^1.0.0" micromark-util-character "^1.0.0" @@ -6513,9 +6773,9 @@ micromark-extension-gfm-tagfilter@^1.0.0: micromark-util-types "^1.0.0" micromark-extension-gfm-task-list-item@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.4.tgz#4b66d87847de40cef2b5ceddb9f9629a6dfe7472" - integrity sha512-9XlIUUVnYXHsFF2HZ9jby4h3npfX10S1coXTnV035QGPgrtNYQq3J6IfIvcCIUAJrrqBVi5BqA/LmaOMJqPwMQ== + version "1.0.5" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz#b52ce498dc4c69b6a9975abafc18f275b9dde9f4" + integrity sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ== dependencies: micromark-factory-space "^1.0.0" micromark-util-character "^1.0.0" @@ -6524,9 +6784,9 @@ micromark-extension-gfm-task-list-item@^1.0.0: uvu "^0.5.0" micromark-extension-gfm@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz#40f3209216127a96297c54c67f5edc7ef2d1a2a2" - integrity sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA== + version "2.0.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz#e517e8579949a5024a493e49204e884aa74f5acf" + integrity sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ== dependencies: micromark-extension-gfm-autolink-literal "^1.0.0" micromark-extension-gfm-footnote "^1.0.0" @@ -6538,18 +6798,18 @@ micromark-extension-gfm@^2.0.0: micromark-util-types "^1.0.0" micromark-factory-destination@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" - integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz#eb815957d83e6d44479b3df640f010edad667b9f" + integrity sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg== dependencies: micromark-util-character "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" micromark-factory-label@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137" - integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz#cc95d5478269085cfa2a7282b3de26eb2e2dec68" + integrity sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w== dependencies: micromark-util-character "^1.0.0" micromark-util-symbol "^1.0.0" @@ -6557,28 +6817,27 @@ micromark-factory-label@^1.0.0: uvu "^0.5.0" micromark-factory-space@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" - integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz#c8f40b0640a0150751d3345ed885a080b0d15faf" + integrity sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ== dependencies: micromark-util-character "^1.0.0" micromark-util-types "^1.0.0" micromark-factory-title@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f" - integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz#dd0fe951d7a0ac71bdc5ee13e5d1465ad7f50ea1" + integrity sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ== dependencies: micromark-factory-space "^1.0.0" micromark-util-character "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" - uvu "^0.5.0" micromark-factory-whitespace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" - integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz#798fb7489f4c8abafa7ca77eed6b5745853c9705" + integrity sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ== dependencies: micromark-factory-space "^1.0.0" micromark-util-character "^1.0.0" @@ -6586,48 +6845,48 @@ micromark-factory-whitespace@^1.0.0: micromark-util-types "^1.0.0" micromark-util-character@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" - integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz#4fedaa3646db249bc58caeb000eb3549a8ca5dcc" + integrity sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg== dependencies: micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" micromark-util-chunked@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" - integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz#37a24d33333c8c69a74ba12a14651fd9ea8a368b" + integrity sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ== dependencies: micromark-util-symbol "^1.0.0" micromark-util-classify-character@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" - integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz#6a7f8c8838e8a120c8e3c4f2ae97a2bff9190e9d" + integrity sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw== dependencies: micromark-util-character "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-types "^1.0.0" micromark-util-combine-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" - integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz#192e2b3d6567660a85f735e54d8ea6e3952dbe84" + integrity sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA== dependencies: micromark-util-chunked "^1.0.0" micromark-util-types "^1.0.0" micromark-util-decode-numeric-character-reference@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" - integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz#b1e6e17009b1f20bc652a521309c5f22c85eb1c6" + integrity sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw== dependencies: micromark-util-symbol "^1.0.0" micromark-util-decode-string@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02" - integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz#dc12b078cba7a3ff690d0203f95b5d5537f2809c" + integrity sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ== dependencies: decode-named-character-reference "^1.0.0" micromark-util-character "^1.0.0" @@ -6635,42 +6894,42 @@ micromark-util-decode-string@^1.0.0: micromark-util-symbol "^1.0.0" micromark-util-encode@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" - integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz#92e4f565fd4ccb19e0dcae1afab9a173bbeb19a5" + integrity sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw== micromark-util-html-tag-name@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497" - integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz#48fd7a25826f29d2f71479d3b4e83e94829b3588" + integrity sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q== micromark-util-normalize-identifier@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" - integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz#7a73f824eb9f10d442b4d7f120fecb9b38ebf8b7" + integrity sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q== dependencies: micromark-util-symbol "^1.0.0" micromark-util-resolve-all@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" - integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz#4652a591ee8c8fa06714c9b54cd6c8e693671188" + integrity sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA== dependencies: micromark-util-types "^1.0.0" micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz#f12e07a85106b902645e0364feb07cf253a85aee" - integrity sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d" + integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A== dependencies: micromark-util-character "^1.0.0" micromark-util-encode "^1.0.0" micromark-util-symbol "^1.0.0" micromark-util-subtokenize@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105" - integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz#941c74f93a93eaf687b9054aeb94642b0e92edb1" + integrity sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A== dependencies: micromark-util-chunked "^1.0.0" micromark-util-symbol "^1.0.0" @@ -6678,19 +6937,19 @@ micromark-util-subtokenize@^1.0.0: uvu "^0.5.0" micromark-util-symbol@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e" - integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz#813cd17837bdb912d069a12ebe3a44b6f7063142" + integrity sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag== micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20" - integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w== + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz#e6676a8cae0bb86a2171c498167971886cb7e283" + integrity sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg== micromark@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.1.0.tgz#eeba0fe0ac1c9aaef675157b52c166f125e89f62" - integrity sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA== + version "3.2.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.2.0.tgz#1af9fef3f995ea1ea4ac9c7e2f19c48fd5c006e9" + integrity sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA== dependencies: "@types/debug" "^4.0.0" debug "^4.0.0" @@ -6747,11 +7006,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.3.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -6767,18 +7021,10 @@ mimic-response@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== - dependencies: - "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" - mini-css-extract-plugin@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz#9a1251d15f2035c342d99a468ab9da7a0451b71e" - integrity sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg== + version "2.7.6" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz#282a3d38863fddcd2e0c220aaed5b90bc156564d" + integrity sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw== dependencies: schema-utils "^4.0.0" @@ -6795,9 +7041,9 @@ minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: brace-expansion "^1.1.7" minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: version "0.5.3" @@ -6809,6 +7055,11 @@ mri@^1.1.0: resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== +mrmime@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" + integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6819,7 +7070,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: +ms@2.1.3, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -6832,16 +7083,25 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== napi-build-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== +needle@^3.1.0, needle@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-3.2.0.tgz#07d240ebcabfd65c76c03afae7f6defe6469df44" + integrity sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ== + dependencies: + debug "^3.2.6" + iconv-lite "^0.6.3" + sax "^1.2.4" + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -6852,6 +7112,11 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -6861,16 +7126,16 @@ no-case@^3.0.4: tslib "^2.0.3" node-abi@^3.3.0: - version "3.24.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.24.0.tgz#b9d03393a49f2c7e147d0c99f180e680c27c1599" - integrity sha512-YPG3Co0luSu6GwOBsmIdGW6Wx0NyNDLg/hriIyDllVsNwnI6UeqaWShxC3lbH4LtEQUgoLP3XR1ndXiDAWvmRw== + version "3.47.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.47.0.tgz#6cbfa2916805ae25c2b7156ca640131632eb05e8" + integrity sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A== dependencies: semver "^7.3.5" node-addon-api@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.0.0.tgz#7d7e6f9ef89043befdb20c1989c905ebde18c501" - integrity sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA== + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== node-emoji@^1.10.0: version "1.11.0" @@ -6884,10 +7149,10 @@ node-fetch@2.6.1: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-fetch@2.6.7, node-fetch@^2.6.1: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== +node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -6896,10 +7161,15 @@ node-forge@^1: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== +node-gyp-build@^4.3.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" + integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== + +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== normalize-path@^2.1.1: version "2.1.1" @@ -6940,7 +7210,7 @@ nprogress@^0.2.0: resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== -nth-check@^2.0.0, nth-check@^2.0.1: +nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== @@ -6953,9 +7223,9 @@ object-assign@^4.1.0, object-assign@^4.1.1: integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== object-keys@^1.1.1: version "1.1.1" @@ -7004,9 +7274,9 @@ onetime@^5.1.2: mimic-fn "^2.1.0" open@^8.0.9, open@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" - integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== dependencies: define-lazy-prop "^2.0.0" is-docker "^2.1.1" @@ -7187,7 +7457,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -7219,7 +7489,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -7246,12 +7516,12 @@ postcss-calc@^8.2.3: postcss-selector-parser "^6.0.9" postcss-value-parser "^4.2.0" -postcss-colormin@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" - integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== +postcss-colormin@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f" + integrity sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" caniuse-api "^3.0.0" colord "^2.9.1" postcss-value-parser "^4.2.0" @@ -7292,13 +7562,13 @@ postcss-discard-unused@^5.1.0: postcss-selector-parser "^6.0.5" postcss-loader@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.1.tgz#4c883cc0a1b2bfe2074377b7a74c1cd805684395" - integrity sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ== + version "7.3.3" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.3.tgz#6da03e71a918ef49df1bb4be4c80401df8e249dd" + integrity sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA== dependencies: - cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.7" + cosmiconfig "^8.2.0" + jiti "^1.18.2" + semver "^7.3.8" postcss-merge-idents@^5.1.1: version "5.1.1" @@ -7316,10 +7586,10 @@ postcss-merge-longhand@^5.1.7: postcss-value-parser "^4.2.0" stylehacks "^5.1.1" -postcss-merge-rules@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz#8f97679e67cc8d08677a6519afca41edf2220894" - integrity sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA== +postcss-merge-rules@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c" + integrity sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" @@ -7363,10 +7633,10 @@ postcss-modules-extract-imports@^3.0.0: resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +postcss-modules-local-by-default@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz#b08eb4f083050708998ba2c6061b50c2870ca524" + integrity sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA== dependencies: icss-utils "^5.0.0" postcss-selector-parser "^6.0.2" @@ -7464,10 +7734,10 @@ postcss-reduce-idents@^5.2.0: dependencies: postcss-value-parser "^4.2.0" -postcss-reduce-initial@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz#c18b7dfb88aee24b1f8e4936541c29adbd35224e" - integrity sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w== +postcss-reduce-initial@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6" + integrity sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" @@ -7480,17 +7750,17 @@ postcss-reduce-transforms@^5.1.0: postcss-value-parser "^4.2.0" postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.10" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" - integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" postcss-sort-media-queries@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz#f48a77d6ce379e86676fc3f140cf1b10a06f6051" - integrity sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg== + version "4.4.1" + resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz#04a5a78db3921eb78f28a1a781a2e68e65258128" + integrity sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw== dependencies: sort-css-media-queries "2.1.0" @@ -7519,12 +7789,12 @@ postcss-zindex@^5.1.0: resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== -postcss@^8.3.11, postcss@^8.4.13, postcss@^8.4.14, postcss@^8.4.7: - version "8.4.16" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c" - integrity sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ== +postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.17, postcss@^8.4.21: + version "8.4.29" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.29.tgz#33bc121cf3b3688d4ddef50be869b2a54185a1dd" + integrity sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw== dependencies: - nanoid "^3.3.4" + nanoid "^3.3.6" picocolors "^1.0.0" source-map-js "^1.0.2" @@ -7552,9 +7822,9 @@ prepend-http@^2.0.0: integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== prettier@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c" - integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA== + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-error@^4.0.0: version "4.0.0" @@ -7584,6 +7854,11 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" @@ -7599,16 +7874,7 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.0.0, prop-types@^15.7.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.8.1" - -prop-types@^15.6.2: +prop-types@^15.0.0, prop-types@^15.6.2, prop-types@^15.7.2: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -7645,16 +7911,16 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +punycode@2.x.x, punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - pupa@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" @@ -7667,10 +7933,15 @@ pure-color@^1.2.0: resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== -qs@6.10.3: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== +qrcode.react@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-3.1.0.tgz#5c91ddc0340f768316fbdb8fff2765134c2aecd8" + integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" @@ -7714,52 +7985,51 @@ raw-body@2.5.1: unpipe "1.0.0" rc-align@^4.0.0: - version "4.0.13" - resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-4.0.13.tgz#5aa1b7b9d20e63f18eb12550cac2eb8d5ef3fe4b" - integrity sha512-l/UwiJllPFVLL/bfDpm0W2ySb1heXeSELnmiMRjXiNp0sboO0z7DnjItXQKS8fNRp6CApzRT1+P6pNWZztbbnA== + version "4.0.15" + resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-4.0.15.tgz#2bbd665cf85dfd0b0244c5a752b07565e9098577" + integrity sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" dom-align "^1.7.0" - lodash "^4.17.21" - rc-util "^5.3.0" + rc-util "^5.26.0" resize-observer-polyfill "^1.5.1" -rc-cascader@~3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.7.0.tgz#98134df578ce1cca22be8fb4319b04df4f3dca36" - integrity sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A== +rc-cascader@~3.14.0: + version "3.14.1" + resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.14.1.tgz#495f00b8d047a54fa64df3102f4d6e4a664feaf2" + integrity sha512-fCsgjLIQqYZMhFj9UT+x2ZW4uobx7OP5yivcn6Xto5fuxHaldphsryzCeUVmreQOHEo0RP+032Ip9RDzrKVKJA== dependencies: "@babel/runtime" "^7.12.5" array-tree-filter "^2.1.0" classnames "^2.3.1" - rc-select "~14.1.0" + rc-select "~14.7.0" rc-tree "~5.7.0" - rc-util "^5.6.1" + rc-util "^5.35.0" -rc-checkbox@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/rc-checkbox/-/rc-checkbox-2.3.2.tgz#f91b3678c7edb2baa8121c9483c664fa6f0aefc1" - integrity sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg== +rc-checkbox@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/rc-checkbox/-/rc-checkbox-3.1.0.tgz#6be0d9d8de2cc96fb5e37f9036a1c3e360d0a42d" + integrity sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ== dependencies: "@babel/runtime" "^7.10.1" - classnames "^2.2.1" + classnames "^2.3.2" + rc-util "^5.25.2" -rc-collapse@~3.4.2: - version "3.4.2" - resolved "https://registry.yarnpkg.com/rc-collapse/-/rc-collapse-3.4.2.tgz#1310be7ad4cd0dcfc622c45f6c3b5ffdee403ad7" - integrity sha512-jpTwLgJzkhAgp2Wpi3xmbTbbYExg6fkptL67Uu5LCRVEj6wqmy0DHTjjeynsjOLsppHGHu41t1ELntZ0lEvS/Q== +rc-collapse@~3.7.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/rc-collapse/-/rc-collapse-3.7.1.tgz#bda1f7f80adccf3433c1c15d4d9f9ca09910c727" + integrity sha512-N/7ejyiTf3XElNJBBpxqnZBUuMsQWEOPjB2QkfNvZ/Ca54eAvJXuOD1EGbCWCk2m7v/MSxku7mRpdeaLOCd4Gg== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" rc-motion "^2.3.4" - rc-util "^5.2.1" - shallowequal "^1.1.0" + rc-util "^5.27.0" -rc-dialog@~9.0.0, rc-dialog@~9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-9.0.2.tgz#aadfebdeba145f256c1fac9b9f509f893cdbb5b8" - integrity sha512-s3U+24xWUuB6Bn2Lk/Qt6rufy+uT+QvWkiFhNBcO9APLxcFFczWamaq7x9h8SCuhfc1nHcW4y8NbMsnAjNnWyg== +rc-dialog@~9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-9.1.0.tgz#6bf6fcc0453503b7643e54a5a445e835e3850649" + integrity sha512-5ry+JABAWEbaKyYsmITtrJbZbJys8CtMyzV8Xn4LYuXMeUx5XVHNyJRoqLFE4AzBuXXzOWeaC49cg+XkxK6kHA== dependencies: "@babel/runtime" "^7.10.1" "@rc-component/portal" "^1.0.0-8" @@ -7767,294 +8037,284 @@ rc-dialog@~9.0.0, rc-dialog@~9.0.2: rc-motion "^2.3.0" rc-util "^5.21.0" -rc-drawer@~6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/rc-drawer/-/rc-drawer-6.0.3.tgz#09993ecdf88ddd569d5a3341d907e3ab258096bb" - integrity sha512-u4RajgrnREKQH/21gB2JHZiA6ZECo0X0BbmDxAJEhKD9jUhlAbqMN5I9VWa4PSzi9ceLHUShqQcPAh2EJswffw== +rc-drawer@~6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/rc-drawer/-/rc-drawer-6.2.0.tgz#fddf4825b0fa9d60e317b996f70278d594d1f668" + integrity sha512-spPkZ3WvP0U0vy5dyzSwlUJ/+vLFtjP/cTwSwejhQRoDBaexSZHsBhELoCZcEggI7LQ7typmtG30lAue2HEhvA== dependencies: "@babel/runtime" "^7.10.1" - "@rc-component/portal" "^1.0.0-6" + "@rc-component/portal" "^1.1.1" classnames "^2.2.6" rc-motion "^2.6.1" rc-util "^5.21.2" -rc-dropdown@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-4.0.1.tgz#f65d9d3d89750241057db59d5a75e43cd4576b68" - integrity sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g== +rc-dropdown@~4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-4.1.0.tgz#418a68939631520de80d0865d02b440eeeb4168e" + integrity sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw== dependencies: "@babel/runtime" "^7.18.3" + "@rc-component/trigger" "^1.7.0" classnames "^2.2.6" - rc-trigger "^5.3.1" rc-util "^5.17.0" -rc-field-form@~1.27.0: - version "1.27.3" - resolved "https://registry.yarnpkg.com/rc-field-form/-/rc-field-form-1.27.3.tgz#e5262796b91c80848a42a3e7a669bf459f08d63d" - integrity sha512-HGqxHnmGQgkPApEcikV4qTg3BLPC82uB/cwBDftDt1pYaqitJfSl5TFTTUMKVEJVT5RqJ2Zi68ME1HmIMX2HAw== +rc-field-form@~1.36.0: + version "1.36.2" + resolved "https://registry.yarnpkg.com/rc-field-form/-/rc-field-form-1.36.2.tgz#0a4e75ab9849e3c2517b8b07c1f97ecd3e52db55" + integrity sha512-tCF/JjUsnxW80Gk4E4ZH74ONsaQMxVTRtui6XhQB8DJc4FHWLLa5pP8zwhxtPKC5NaO0QZ0Cv79JggDubn6n2g== dependencies: "@babel/runtime" "^7.18.0" async-validator "^4.1.0" - rc-util "^5.8.0" + rc-util "^5.32.2" -rc-image@~5.12.0: - version "5.12.1" - resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-5.12.1.tgz#1560eda00ef9d33ebdb3c8c74ab134eb00f973d4" - integrity sha512-FMldR/ODwQmlFlhjR4c6hsOHmnn4s9CxmW7PR/9XCYE1XHlGJ5OkSWOtJruoaLjVwt2tQYDRnLANf/mKZ9ReUg== +rc-image@~7.1.0: + version "7.1.3" + resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-7.1.3.tgz#0072547c7c0a70e6badfb4bee320806c5bf7427b" + integrity sha512-foMl1rcit1F0+vgxE5kf0c8TygQcHhILsOohQUL+JMUbzOo3OBFRcehJudYbqbCTArzCecS8nA1irUU9vvgQbg== dependencies: "@babel/runtime" "^7.11.2" "@rc-component/portal" "^1.0.2" classnames "^2.2.6" - rc-dialog "~9.0.0" - rc-util "^5.0.6" + rc-dialog "~9.1.0" + rc-motion "^2.6.2" + rc-util "^5.34.1" -rc-input-number@~7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-7.4.0.tgz#b8b4ffa8bbc04198e79ce8b9611756d046d128ec" - integrity sha512-r/Oub/sPYbzqLNUOHnnc9sbCu78a81KX+RCbRwmpvB4W6nptUySbdWS5KHV4Hak5CAE1LAd+wWm5JjvZizG1FA== +rc-input-number@~8.0.2: + version "8.0.4" + resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-8.0.4.tgz#d33cfe4126e10f4771fe11a40797222c76d6598f" + integrity sha512-TP+G5b7mZtbwXJ/YEZXF/OgbEZ6iqD4+RSuxZJ8VGKGXDcdt0FKIvpFoNQr/knspdFC4OxA0OfsWfFWfN4XSyA== dependencies: "@babel/runtime" "^7.10.1" "@rc-component/mini-decimal" "^1.0.1" classnames "^2.2.5" - rc-util "^5.23.0" + rc-input "~1.1.0" + rc-util "^5.28.0" -rc-input@~0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-0.1.4.tgz#45cb4ba209ae6cc835a2acb8629d4f8f0cb347e0" - integrity sha512-FqDdNz+fV2dKNgfXzcSLKvC+jEs1709t7nD+WdfjrdSaOcefpgc7BUJYadc3usaING+b7ediMTfKxuJBsEFbXA== +rc-input@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-1.1.1.tgz#af33b49272220f6d42852d21b22e84c2dc1a87e6" + integrity sha512-NTR1Z4em681L8/ewb2KR80RykSmN8I2mzqzJDCoUmTrV1BB9Hk5d7ha4TnfgdEPPL148N+603sW2LExSXk1IbA== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-util "^5.18.1" -rc-mentions@~1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-1.13.1.tgz#c884b70e1505a197f1b32a7c6b39090db6992a72" - integrity sha512-FCkaWw6JQygtOz0+Vxz/M/NWqrWHB9LwqlY2RtcuFqWJNFK9njijOOzTSsBGANliGufVUzx/xuPHmZPBV0+Hgw== +rc-mentions@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-2.5.0.tgz#8b936e497e0deb922f40df46e42efc3f596ec207" + integrity sha512-rERXsbUTNVrb5T/iDC0ki/SRGWJnOVraDy6O25Us3FSpuUZ3uq2TPZB4fRk0Hss5kyiEPzz2sprhkI4b+F4jUw== dependencies: - "@babel/runtime" "^7.10.1" + "@babel/runtime" "^7.22.5" + "@rc-component/trigger" "^1.5.0" classnames "^2.2.6" - rc-menu "~9.8.0" - rc-textarea "^0.4.0" - rc-trigger "^5.0.4" + rc-input "~1.1.0" + rc-menu "~9.10.0" + rc-textarea "~1.3.0" rc-util "^5.22.5" -rc-menu@~9.8.0: - version "9.8.1" - resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-9.8.1.tgz#988cd807f78d2f92eab686f6813f50b165f78405" - integrity sha512-179weouypfjWJSRvvoo/vPy+StojsMzK2XC5jRNhL1ryt/N/8wAFESte8K6jZJkNp9DHDLFTe+dCGmikKpiFuA== +rc-menu@~9.10.0: + version "9.10.0" + resolved "https://registry.yarnpkg.com/rc-menu/-/rc-menu-9.10.0.tgz#5e0982e26786d67c8ebdba50406b197884c749a7" + integrity sha512-g27kpXaAoJh/fkPZF65/d4V+w4DhDeqomBdPcGnkFAcJnEM4o21TnVccrBUoDedLKzC7wJRw1Q7VTqEsfEufmw== dependencies: "@babel/runtime" "^7.10.1" + "@rc-component/trigger" "^1.6.2" classnames "2.x" rc-motion "^2.4.3" - rc-overflow "^1.2.8" - rc-trigger "^5.1.2" - rc-util "^5.12.0" - shallowequal "^1.1.0" + rc-overflow "^1.3.1" + rc-util "^5.27.0" -rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.0, rc-motion@^2.6.1, rc-motion@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.6.2.tgz#3d31f97e41fb8e4f91a4a4189b6a98ac63342869" - integrity sha512-4w1FaX3dtV749P8GwfS4fYnFG4Rb9pxvCYPc/b2fw1cmlHJWNNgOFIz7ysiD+eOrzJSvnLJWlNQQncpNMXwwpg== +rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.0, rc-motion@^2.6.1, rc-motion@^2.6.2, rc-motion@^2.7.3: + version "2.8.0" + resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.8.0.tgz#5a8231632d7f5304873661424f293d6ee389854b" + integrity sha512-9gWWzlPvx/IJANj+t+ArqLCQ43rCWYLpOUe6+WJSAGb+b+fqBcfx81qPhg6b+ewa6g3mGNDhkTpBrVrCC4gcXA== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-util "^5.21.0" -rc-notification@~5.0.0-alpha.9: - version "5.0.0-alpha.9" - resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-5.0.0-alpha.9.tgz#e6fbf5cc786e508f022691a61a03c0473f5ca7b0" - integrity sha512-QPvq8VHe2M0SE5DHJf7ADWlvfWKnTsj5FVxcu39gdjX98kKmi+BHY1eTPAQkkdGqd6ZXv6xXHl8qKHyWhQcFPA== +rc-notification@~5.0.4: + version "5.0.5" + resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-5.0.5.tgz#33a86864b7491749742cfaef0df0117a9b967926" + integrity sha512-uEz2jggourwv/rR0obe7RHEa63UchqX4k+e+Qt2c3LaY7U9Tc+L6ANhzgCKYSA/afm0ebjmNZHoB5Cv47xEOcA== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" rc-motion "^2.6.0" rc-util "^5.20.1" -rc-overflow@^1.0.0, rc-overflow@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc-overflow/-/rc-overflow-1.2.8.tgz#40f140fabc244118543e627cdd1ef750d9481a88" - integrity sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ== +rc-overflow@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/rc-overflow/-/rc-overflow-1.3.2.tgz#72ee49e85a1308d8d4e3bd53285dc1f3e0bcce2c" + integrity sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-resize-observer "^1.0.0" - rc-util "^5.19.2" + rc-util "^5.37.0" -rc-pagination@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-3.2.0.tgz#4f2fdba9fdac0f48e5c9fb1141973818138af7e1" - integrity sha512-5tIXjB670WwwcAJzAqp2J+cOBS9W3cH/WU1EiYwXljuZ4vtZXKlY2Idq8FZrnYBz8KhN3vwPo9CoV/SJS6SL1w== +rc-pagination@~3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-3.6.1.tgz#2db6678a57cd2f4f29d6c0416e282543af52d0df" + integrity sha512-R/sUnKKXx1Nm4kZfUKS3YKa7yEPF1ZkVB/AynQaHt+nMER7h9wPTfliDJFdYo+RM/nk2JD4Yc5QpUq8fIQHeug== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.1" + rc-util "^5.32.2" -rc-picker@~3.1.1: - version "3.1.4" - resolved "https://registry.yarnpkg.com/rc-picker/-/rc-picker-3.1.4.tgz#4806dc36a78424abaee610830777c8e22a23c74c" - integrity sha512-4qANXNc3C02YENNQvun329zf9VLvSQ2W8RkKQRu8k1P+EtSGqe3klcAKCfz/1TuCiDvgRjJlzRmyZAkwvsbI8w== +rc-picker@~3.13.0: + version "3.13.1" + resolved "https://registry.yarnpkg.com/rc-picker/-/rc-picker-3.13.1.tgz#06adc7b1ccbcfa05ff1ac9aae0c696fb5546f20d" + integrity sha512-211SrinX5IXZ9FMMDUMyPLuGOdfftUtd8zj4lqudpFxlMdtgV5+hXUJMBKb26xmDsleOm5iySK6KIHgiaI+U4w== dependencies: "@babel/runtime" "^7.10.1" + "@rc-component/trigger" "^1.5.0" classnames "^2.2.1" - rc-trigger "^5.0.4" - rc-util "^5.4.0" - shallowequal "^1.1.0" + rc-util "^5.30.0" rc-progress@~3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/rc-progress/-/rc-progress-3.4.1.tgz#a9ffe099e88a4fc03afb09d8603162bf0760d743" - integrity sha512-eAFDHXlk8aWpoXl0llrenPMt9qKHQXphxcVsnKs0FHC6eCSk1ebJtyaVjJUzKe0233ogiLDeEFK1Uihz3s67hw== + version "3.4.2" + resolved "https://registry.yarnpkg.com/rc-progress/-/rc-progress-3.4.2.tgz#f8df9ee95e790490171ab6b31bf07303cdc79980" + integrity sha512-iAGhwWU+tsayP+Jkl9T4+6rHeQTG9kDz8JAHZk4XtQOcYN5fj9H34NXNEdRdZx94VUDHMqCb1yOIvi8eJRh67w== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.6" rc-util "^5.16.1" -rc-rate@~2.9.0: - version "2.9.2" - resolved "https://registry.yarnpkg.com/rc-rate/-/rc-rate-2.9.2.tgz#4a58965d1ecf91896ebae01d458b59056df0b4ea" - integrity sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g== +rc-rate@~2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/rc-rate/-/rc-rate-2.12.0.tgz#0182deffed3b009cdcc61660da8746c39ed91ed5" + integrity sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.5" rc-util "^5.0.1" -rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.2.0.tgz#9f46052f81cdf03498be35144cb7c53fd282c4c7" - integrity sha512-6W+UzT3PyDM0wVCEHfoW3qTHPTvbdSgiA43buiy8PzmeMnfgnDeb9NjdimMXMl3/TcrvvWl5RRVdp+NqcR47pQ== +rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.2.0, rc-resize-observer@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.3.1.tgz#b61b9f27048001243617b81f95e53d7d7d7a6a3d" + integrity sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg== dependencies: - "@babel/runtime" "^7.10.1" + "@babel/runtime" "^7.20.7" classnames "^2.2.1" - rc-util "^5.15.0" + rc-util "^5.27.0" resize-observer-polyfill "^1.5.1" -rc-segmented@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rc-segmented/-/rc-segmented-2.1.0.tgz#0e0afe646c1a0e44a0e18785f518c42633ec8efc" - integrity sha512-hUlonro+pYoZcwrH6Vm56B2ftLfQh046hrwif/VwLIw1j3zGt52p5mREBwmeVzXnSwgnagpOpfafspzs1asjGw== +rc-segmented@~2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/rc-segmented/-/rc-segmented-2.2.2.tgz#a34f12ce6c0975fc3042ae7656bcd18e1744798e" + integrity sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-motion "^2.4.4" rc-util "^5.17.0" -rc-select@~14.1.0, rc-select@~14.1.13: - version "14.1.16" - resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.1.16.tgz#0cc4b5a1fc551a2db7c96bc1ece0896317ecdd47" - integrity sha512-71XLHleuZmufpdV2vis5oituRkhg2WNvLpVMJBGWRar6WGAVOHXaY9DR5HvwWry3EGTn19BqnL6Xbybje6f8YA== +rc-select@~14.7.0, rc-select@~14.7.1: + version "14.7.4" + resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.7.4.tgz#742d85861e83604237784f60e2ba9dabcde8eac9" + integrity sha512-qRUpvMVXFy6rdHe+qzHXAqyQAfhErC/oY8dcRtoRjoz0lz2Nx3J+lLL5AnEbjnwlS+/kQTJUZ/65WyCwWwcLwQ== dependencies: "@babel/runtime" "^7.10.1" + "@rc-component/trigger" "^1.5.0" classnames "2.x" rc-motion "^2.0.1" - rc-overflow "^1.0.0" - rc-trigger "^5.0.4" + rc-overflow "^1.3.1" rc-util "^5.16.1" - rc-virtual-list "^3.2.0" + rc-virtual-list "^3.5.2" -rc-slider@~10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-10.0.1.tgz#7058c68ff1e1aa4e7c3536e5e10128bdbccb87f9" - integrity sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q== +rc-slider@~10.1.0: + version "10.1.1" + resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-10.1.1.tgz#5e82036e60b61021aba3ea0e353744dd7c74e104" + integrity sha512-gn8oXazZISEhnmRinI89Z/JD/joAaM35jp+gDtIVSTD/JJMCCBqThqLk1SVJmvtfeiEF/kKaFY0+qt4SDHFUDw== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.5" - rc-util "^5.18.1" - shallowequal "^1.1.0" + rc-util "^5.27.0" -rc-steps@~6.0.0-alpha.2: - version "6.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/rc-steps/-/rc-steps-6.0.0-alpha.2.tgz#505e64177111becd911cef4d24f15477438c9e59" - integrity sha512-d/GPx7ATlPbtFeOVt5FB19W11OBCmRd7lLknt4aSoCI6ukwJqpEhWu2INN4pDOQqN04y3PDsWl1q9hnw+ZC5AA== +rc-steps@~6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/rc-steps/-/rc-steps-6.0.1.tgz#c2136cd0087733f6d509209a84a5c80dc29a274d" + integrity sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g== dependencies: "@babel/runtime" "^7.16.7" classnames "^2.2.3" rc-util "^5.16.1" -rc-switch@~4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/rc-switch/-/rc-switch-4.0.0.tgz#55fbf99fc2d680791175037d379e170ba51fbe78" - integrity sha512-IfrYC99vN0gKaTyjQdqYuADU0eH00SAFHg3jOp8HrmUpJruhV1SohJzrCbPqPraZeX/6X/QKkdLfkdnUub05WA== +rc-switch@~4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rc-switch/-/rc-switch-4.1.0.tgz#f37d81b4e0c5afd1274fd85367b17306bf25e7d7" + integrity sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg== dependencies: - "@babel/runtime" "^7.10.1" + "@babel/runtime" "^7.21.0" classnames "^2.2.1" - rc-util "^5.0.1" + rc-util "^5.30.0" -rc-table@~7.26.0: - version "7.26.0" - resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.26.0.tgz#9d517e7fa512e7571fdcc453eb1bf19edfac6fbc" - integrity sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ== +rc-table@~7.32.1: + version "7.32.3" + resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.32.3.tgz#9773563dc206ff12b6f023b7223b7056908d6241" + integrity sha512-MqjrI/ibuGg7NEyFsux0dM5GK+3er1gTiZofAkifr2bHf/Sa1nUqXXFmSrYXSOjwpx0xyBnJ3GrHFCIqC/eOzw== dependencies: "@babel/runtime" "^7.10.1" + "@rc-component/context" "^1.3.0" classnames "^2.2.5" rc-resize-observer "^1.1.0" - rc-util "^5.22.5" - shallowequal "^1.1.0" + rc-util "^5.27.1" -rc-tabs@~12.4.2: - version "12.4.2" - resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-12.4.2.tgz#487a1b3f8d8cf0bfc121224013dab00d4a8e0532" - integrity sha512-FFlGwuTjQUznWzJtyhmHc6KAp5lRQFxKUv9Aj1UtsOYe2e7WGmuzcrd+/LQchuPe0VjhaZPdGkmFGcqGqNO6ow== +rc-tabs@~12.9.0: + version "12.9.0" + resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-12.9.0.tgz#6d9af43d8ad2c47be00c75bee92417a4842d29d2" + integrity sha512-2HnVowgMVrq0DfQtyu4mCd9E6pXlWNdM6VaDvOOHMsLYqPmpY+7zBqUC6YrrQ9xYXHciTS0e7TtjOHIvpVCHLQ== dependencies: "@babel/runtime" "^7.11.2" classnames "2.x" - rc-dropdown "~4.0.0" - rc-menu "~9.8.0" + rc-dropdown "~4.1.0" + rc-menu "~9.10.0" rc-motion "^2.6.2" rc-resize-observer "^1.0.0" rc-util "^5.16.0" -rc-textarea@^0.4.0, rc-textarea@~0.4.5: - version "0.4.7" - resolved "https://registry.yarnpkg.com/rc-textarea/-/rc-textarea-0.4.7.tgz#627f662d46f99e0059d1c1ebc8db40c65339fe90" - integrity sha512-IQPd1CDI3mnMlkFyzt2O4gQ2lxUsnBAeJEoZGJnkkXgORNqyM9qovdrCj9NzcRfpHgLdzaEbU3AmobNFGUznwQ== +rc-textarea@~1.3.0, rc-textarea@~1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/rc-textarea/-/rc-textarea-1.3.4.tgz#e77baf2202ac8f7e34a50ec9e15dd1dcb1501455" + integrity sha512-wn0YjTpvcVolcfXa0HtzL+jgV2QcwtfB29RwNAKj8hMgZOju1V24M3TfEDjABeQEAQbUGbjMbISREOX/YSVKhg== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.1" + rc-input "~1.1.0" rc-resize-observer "^1.0.0" - rc-util "^5.24.4" - shallowequal "^1.1.0" + rc-util "^5.27.0" -rc-tooltip@~5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-5.2.2.tgz#e5cafa8ecebf78108936a0bcb93c150fa81ac93b" - integrity sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg== +rc-tooltip@~6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-6.0.1.tgz#6a5e33bd6c3f6afe8851ea90e7af43e5c26b3cc6" + integrity sha512-MdvPlsD1fDSxKp9+HjXrc/CxLmA/s11QYIh1R7aExxfodKP7CZA++DG1AjrW80F8IUdHYcR43HAm0Y2BYPelHA== dependencies: "@babel/runtime" "^7.11.2" + "@rc-component/trigger" "^1.0.4" classnames "^2.3.1" - rc-trigger "^5.0.0" -rc-tree-select@~5.5.4: - version "5.5.5" - resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-5.5.5.tgz#d28b3b45da1e820cd21762ba0ee93c19429bb369" - integrity sha512-k2av7jF6tW9bIO4mQhaVdV4kJ1c54oxV3/hHVU+oD251Gb5JN+m1RbJFTMf1o0rAFqkvto33rxMdpafaGKQRJw== +rc-tree-select@~5.11.0: + version "5.11.2" + resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-5.11.2.tgz#66b4a95843c6c1e04ba923a485e8b13def3ad6d0" + integrity sha512-ujRFO3pcjSg8R4ndXX2oiNcCu+RgO9ZPcd23CZy18Khm+nRsfWWS3Su7qB0iuoJgzAJ5LK7b6Dio0t7IQDGs9g== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" - rc-select "~14.1.0" + rc-select "~14.7.0" rc-tree "~5.7.0" rc-util "^5.16.1" -rc-tree@~5.7.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-5.7.2.tgz#270ea7d9e1b2e5e81cd3659eba2fbd022a4831f6" - integrity sha512-nmnL6qLnfwVckO5zoqKL2I9UhwDqzyCtjITQCkwhimyz1zfuFkG5ZPIXpzD/Guzso94qQA/QrMsvzic5W6QDjg== +rc-tree@~5.7.0, rc-tree@~5.7.6: + version "5.7.10" + resolved "https://registry.yarnpkg.com/rc-tree/-/rc-tree-5.7.10.tgz#3d66c2a81ffd24cbb8b816e7a747f626e57cb0fc" + integrity sha512-n4UkMQY3bzvJUNnbw6e3YI7sy2kE9c9vAYbSt94qAhcPKtMOThONNr1LIaFB/M5XeFYYrWVbvRVoT8k38eFuSQ== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" rc-motion "^2.0.1" rc-util "^5.16.1" - rc-virtual-list "^3.4.8" - -rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2, rc-trigger@^5.2.10, rc-trigger@^5.3.1, rc-trigger@^5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-5.3.4.tgz#6b4b26e32825677c837d1eb4d7085035eecf9a61" - integrity sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw== - dependencies: - "@babel/runtime" "^7.18.3" - classnames "^2.2.6" - rc-align "^4.0.0" - rc-motion "^2.0.0" - rc-util "^5.19.2" + rc-virtual-list "^3.5.1" rc-upload@~4.3.0: version "4.3.4" @@ -8065,35 +8325,25 @@ rc-upload@~4.3.0: classnames "^2.2.5" rc-util "^5.2.0" -rc-util@^5.0.1, rc-util@^5.0.6, rc-util@^5.12.0, rc-util@^5.15.0, rc-util@^5.16.0, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.19.2, rc-util@^5.2.0, rc-util@^5.2.1, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.21.2, rc-util@^5.22.5, rc-util@^5.23.0, rc-util@^5.24.2, rc-util@^5.24.4, rc-util@^5.25.2, rc-util@^5.3.0, rc-util@^5.4.0, rc-util@^5.6.1, rc-util@^5.8.0: - version "5.25.3" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.25.3.tgz#7f6a5895e4edc5acdf5f73e90e1c031f3b67257d" - integrity sha512-+M+44T6UdM4iOd4QXRQKQjitOY26vC5pgFPNSo0XsY9OWzpHvy77BI55eL9Q9oDMUHzVuRNzzUkK1RI2W3n+ZQ== +rc-util@^5.0.1, rc-util@^5.16.0, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2.0, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.21.2, rc-util@^5.22.5, rc-util@^5.24.4, rc-util@^5.25.2, rc-util@^5.26.0, rc-util@^5.27.0, rc-util@^5.27.1, rc-util@^5.28.0, rc-util@^5.30.0, rc-util@^5.31.1, rc-util@^5.32.2, rc-util@^5.33.0, rc-util@^5.34.1, rc-util@^5.35.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.9.4: + version "5.37.0" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.37.0.tgz#6df9a55cb469b41b6995530a45b5f3dd3219a4ea" + integrity sha512-cPMV8DzaHI1KDaS7XPRXAf4J7mtBqjvjikLpQieaeOO7+cEbqY2j7Kso/T0R0OiEZTNcLS/8Zl9YrlXiO9UbjQ== dependencies: "@babel/runtime" "^7.18.3" react-is "^16.12.0" - shallowequal "^1.1.0" - -rc-util@^5.9.4: - version "5.23.0" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.23.0.tgz#a583b1ec3e1832a80eced7a700a494af0b590743" - integrity sha512-lgm6diJ/pLgyfoZY59Vz7sW4mSoQCgozqbBye9IJ7/mb5w5h4T7h+i2JpXAx/UBQxscBZe68q0sP7EW+qfkKUg== - dependencies: - "@babel/runtime" "^7.18.3" - react-is "^16.12.0" - shallowequal "^1.1.0" -rc-virtual-list@^3.2.0, rc-virtual-list@^3.4.8: - version "3.4.13" - resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.4.13.tgz#20acc934b263abcf7b7c161f50ef82281b2f7e8d" - integrity sha512-cPOVDmcNM7rH6ANotanMDilW/55XnFPw0Jh/GQYtrzZSy3AmWvCnqVNyNC/pgg3lfVmX2994dlzAhuUrd4jG7w== +rc-virtual-list@^3.5.1, rc-virtual-list@^3.5.2: + version "3.10.5" + resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.10.5.tgz#a203ca60bf3334e16193f641db1e99a48ae76574" + integrity sha512-Vc89TL3JHfRlLVQXVj5Hmv0dIflgwmHDcbjt9lrZjOG3wNUDkTF5zci8kFDU/CzdmmqgKu+CUktEpT10VUKYSQ== dependencies: "@babel/runtime" "^7.20.0" classnames "^2.2.6" rc-resize-observer "^1.0.0" - rc-util "^5.15.0" + rc-util "^5.36.0" -rc@^1.2.7, rc@^1.2.8: +rc@1.2.8, rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -8157,9 +8407,9 @@ react-error-overlay@^6.0.11: integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== react-fast-compare@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== + version "3.2.2" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== react-helmet-async@*, react-helmet-async@^1.3.0: version "1.3.0" @@ -8172,7 +8422,7 @@ react-helmet-async@*, react-helmet-async@^1.3.0: react-fast-compare "^3.2.0" shallowequal "^1.1.0" -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -8252,28 +8502,27 @@ react-router-config@^5.1.1: "@babel/runtime" "^7.1.2" react-router-dom@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.3.tgz#8779fc28e6691d07afcaf98406d3812fe6f11199" - integrity sha512-Ov0tGPMBgqmbu5CDmN++tv2HQ9HlWDuWIIqn4b88gjlAN5IHI+4ZUZRcpz9Hl0azFIwihbLDYw1OiHGRo7ZIng== + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" + integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.3.3" + react-router "5.3.4" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.3.3, react-router@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.3.tgz#8e3841f4089e728cf82a429d92cdcaa5e4a3a288" - integrity sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w== +react-router@5.3.4, react-router@^5.3.3: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" + integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" hoist-non-react-statics "^3.1.0" loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" path-to-regexp "^1.7.0" prop-types "^15.6.2" react-is "^16.6.0" @@ -8290,11 +8539,11 @@ react-style-singleton@^2.2.1: tslib "^2.0.0" react-textarea-autosize@^8.3.2: - version "8.4.0" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.4.0.tgz#4d0244d6a50caa897806b8c44abc0540a69bfc8c" - integrity sha512-YrTFaEHLgJsi8sJVYHBzYn+mkP3prGkmP2DKb/tm0t7CLJY5t1Rxix8070LAKb0wby7bl/lf2EeHkuMihMZMwQ== + version "8.5.3" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz#d1e9fe760178413891484847d3378706052dd409" + integrity sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ== dependencies: - "@babel/runtime" "^7.10.2" + "@babel/runtime" "^7.20.13" use-composed-ref "^1.3.0" use-latest "^1.2.1" @@ -8316,9 +8565,9 @@ react@^18.2.0: loose-envify "^1.1.0" readable-stream@^2.0.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -8329,9 +8578,9 @@ readable-stream@^2.0.1: util-deprecate "~1.0.1" readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -8375,41 +8624,36 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.11: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== -regenerator-transform@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" - integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== dependencies: "@babel/runtime" "^7.8.4" -regexpu-core@^5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" - integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== dependencies: + "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" regenerate-unicode-properties "^10.1.0" - regjsgen "^0.7.1" regjsparser "^0.9.1" unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== dependencies: - rc "^1.2.8" + rc "1.2.8" registry-url@^5.0.0: version "5.1.0" @@ -8418,11 +8662,6 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" -regjsgen@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" - integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== - regjsparser@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" @@ -8496,9 +8735,9 @@ remark-parse@8.0.3: xtend "^4.0.1" remark-parse@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" - integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw== + version "10.0.2" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.2.tgz#ca241fde8751c2158933f031a4e3efbaeb8bc262" + integrity sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw== dependencies: "@types/mdast" "^3.0.0" mdast-util-from-markdown "^1.0.0" @@ -8578,12 +8817,13 @@ resolve-pathname@^3.0.0: integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" responselike@^1.0.2: version "1.0.2" @@ -8632,9 +8872,9 @@ run-parallel@^1.1.9: queue-microtask "^1.2.2" rxjs@^7.5.4: - version "7.5.6" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc" - integrity sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw== + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" @@ -8655,15 +8895,15 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sass-loader@^10.1.1: - version "10.2.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.2.0.tgz#3d64c1590f911013b3fa48a0b22a83d5e1494716" - integrity sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw== + version "10.4.1" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.4.1.tgz#bea4e173ddf512c9d7f53e9ec686186146807cbf" + integrity sha512-aX/iJZTTpNUNx/OSYzo2KsjIUQHqvWsAhhUijFjAPdZTEhstjZI9zTNvkTTwsx+uNUJqUwOw5gacxQMx4hJxGQ== dependencies: klona "^2.0.4" loader-utils "^2.0.0" @@ -8672,11 +8912,13 @@ sass-loader@^10.1.1: semver "^7.3.2" sass@^1.43.2: - version "1.43.3" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.43.3.tgz#aa16a69131b84f0cd23189a242571e8905f1ce43" - integrity sha512-BJnLngqWpMeS65UvlYYEuCb3/fLxDxhHtOB/gWPxs6NKrslTxGt3ZxwIvOe/0Jm4tWwM/+tIpE3wj4dLEhPDeQ== + version "1.66.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.66.1.tgz#04b51c4671e4650aa393740e66a4e58b44d055b1" + integrity sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA== dependencies: chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" sax@^1.2.4: version "1.2.4" @@ -8708,31 +8950,31 @@ schema-utils@^2.6.5: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" ajv-keywords "^3.5.2" schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" + ajv "^8.9.0" ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" + ajv-keywords "^5.1.0" scroll-into-view-if-needed@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.3.tgz#57256bef78f3c3c288070d2aaa63cf547aa11e70" - integrity sha512-QoCH0lVw0tbA7Rl6sToH7e1tO3n95Oi6JgBgC8hEpNNZUC91MfasJ/4E1ZdbzGueNDZ+Y7ObfRaelKUgTyPbJA== + version "3.0.10" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz#38fbfe770d490baff0fb2ba34ae3539f6ec44e13" + integrity sha512-t44QCeDKAPf1mtQH3fYpWz8IM/DyvHLjs8wUvvwMYxk5moOqCzrMSxK6HQVD0QVmVjXFavoFIPRVrMuJPKAvtg== dependencies: - compute-scroll-into-view "^2.0.2" + compute-scroll-into-view "^3.0.2" section-matter@^1.0.0: version "1.0.0" @@ -8747,10 +8989,10 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== -selfsigned@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.1.tgz#8b2df7fa56bf014d19b6007655fff209c0ef0a56" - integrity sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ== +selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== dependencies: node-forge "^1" @@ -8762,19 +9004,19 @@ semver-diff@^3.1.1: semver "^6.3.0" semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== +semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" @@ -8797,10 +9039,10 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== +serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== dependencies: randombytes "^2.1.0" @@ -8895,9 +9137,9 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== shelljs@^0.8.5: version "0.8.5" @@ -8918,9 +9160,9 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" - integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== simple-concat@^1.0.0: version "1.0.1" @@ -8943,14 +9185,14 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -sirv@^1.0.7: - version "1.0.18" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.18.tgz#105fab52fb656ce8a2bebbf36b11052005952899" - integrity sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA== +sirv@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.3.tgz#ca5868b87205a74bef62a469ed0296abceccd446" + integrity sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA== dependencies: "@polka/url" "^1.0.0-next.20" - mime "^2.3.1" - totalist "^1.0.0" + mrmime "^1.0.0" + totalist "^3.0.0" sisteransi@^1.0.5: version "1.0.5" @@ -8991,12 +9233,12 @@ sort-css-media-queries@2.1.0: resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== -source-map-js@^1.0.2: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-support@^0.5.17, source-map-support@~0.5.20: +source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -9073,9 +9315,9 @@ statuses@2.0.1: integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== std-env@^3.0.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.2.1.tgz#00e260ec3901333537125f81282b9296b00d7304" - integrity sha512-D/uYFWkI/31OrnKmXZqGAGK5GbQRPp/BWA1nuITcc6ICblhhuQUPHS5E2GSCVS7Hwhf4ciq8qsATwBUxv+lI6w== + version "3.4.3" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.4.3.tgz#326f11db518db751c83fd58574f449b7c3060910" + integrity sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q== string-convert@^0.2.0: version "0.2.1" @@ -9131,9 +9373,9 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: ansi-regex "^5.0.1" strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: ansi-regex "^6.0.1" @@ -9165,9 +9407,9 @@ style-to-object@0.3.0, style-to-object@^0.3.0: inline-style-parser "0.1.1" style-to-object@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.1.tgz#53cf856f7cf7f172d72939d9679556469ba5de37" - integrity sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw== + version "0.4.2" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.2.tgz#a8247057111dea8bd3b8a1a66d2d0c9cf9218a54" + integrity sha512-1JGpfPB3lo42ZX8cuPrheZbfQ6kqPPnPHlKMyeRYtfKD+0jG+QsXgXN57O/dvJlzlB2elI6dGmrPnl5VPQFPaA== dependencies: inline-style-parser "0.1.1" @@ -9180,9 +9422,9 @@ stylehacks@^5.1.1: postcss-selector-parser "^6.0.4" stylis@^4.0.13: - version "4.1.3" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" - integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.0.tgz#abe305a669fc3d8777e10eefcfc73ad861c5588c" + integrity sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ== subscriptions-transport-ws@^0.9.18: version "0.9.19" @@ -9216,6 +9458,11 @@ supports-color@^8.0.0: dependencies: has-flag "^4.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + svg-parser@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" @@ -9278,24 +9525,24 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.3: - version "5.3.6" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" - integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== +terser-webpack-plugin@^5.3.3, terser-webpack-plugin@^5.3.7: + version "5.3.9" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" + integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== dependencies: - "@jridgewell/trace-mapping" "^0.3.14" + "@jridgewell/trace-mapping" "^0.3.17" jest-worker "^27.4.5" schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - terser "^5.14.1" + serialize-javascript "^6.0.1" + terser "^5.16.8" -terser@^5.10.0, terser@^5.14.1: - version "5.15.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" - integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== +terser@^5.10.0, terser@^5.16.8: + version "5.19.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.3.tgz#359baeba615aef13db4b8c4d77a2aa0d8814aa9e" + integrity sha512-pQzJ9UJzM0IgmT4FAtYI6+VqFf0lj/to58AV0Xfgg0Up37RyPG7Al+1cepC6/BVuAxR9oNb41/DL4DEoHJvTdg== dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" @@ -9304,17 +9551,22 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +throttle-debounce@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz#a17a4039e82a2ed38a5e7268e4132d6960d41933" + integrity sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg== + thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== tiny-invariant@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" - integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== -tiny-warning@^1.0.0, tiny-warning@^1.0.3: +tiny-warning@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== @@ -9346,10 +9598,10 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== tr46@~0.0.3: version "0.0.3" @@ -9381,27 +9633,29 @@ trough@^2.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== -ts-node@^9.1.1: - version "9.1.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" - integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== - dependencies: +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" arg "^4.1.0" create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" - source-map-support "^0.5.17" + v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tslib@^2.0.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.1.tgz#f2ad78c367857d54e49a0ef9def68737e1a67b21" - integrity sha512-KaI6gPil5m9vF7DKaoXxx1ia9fxS4qG5YveErRRVknPDXXriu5M8h48YRjB6h5ZUOKuAKlSJYb0GaDe8I39fRw== - -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== tslib@~2.0.1: version "2.0.3" @@ -9448,6 +9702,16 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -9456,14 +9720,14 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" typescript@^4.1.5: - version "4.4.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" - integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -ua-parser-js@^0.7.30: - version "0.7.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" - integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== +ua-parser-js@^1.0.35: + version "1.0.35" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.35.tgz#c4ef44343bc3db0a3cbefdf21822f1b1fc1ab011" + integrity sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA== unherit@^1.0.4: version "1.1.3" @@ -9663,10 +9927,10 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== dependencies: escalade "^3.1.1" picocolors "^1.0.0" @@ -9751,6 +10015,18 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" +use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -9776,6 +10052,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + uvu@^0.5.0: version "0.5.6" resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" @@ -9786,6 +10067,11 @@ uvu@^0.5.0: kleur "^4.0.3" sade "^1.7.3" +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + valid-url@1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" @@ -9889,18 +10175,26 @@ webidl-conversions@^3.0.0: integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== webpack-bundle-analyzer@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.6.1.tgz#bee2ee05f4ba4ed430e4831a319126bb4ed9f5a6" - integrity sha512-oKz9Oz9j3rUciLNfpGFjOb49/jEpXNmWdVH8Ls//zNcnLlQdTGXQQMsBbb/gR7Zl8WNLxVCq+0Hqbx3zv6twBw== + version "4.9.1" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.1.tgz#d00bbf3f17500c10985084f22f1a2bf45cb2f09d" + integrity sha512-jnd6EoYrf9yMxCyYDPj8eutJvtjQNp8PHmni/e/ulydHBWhT5J3menXt3HEkScsu9YqMAcG4CfFjs3rj5pVU1w== dependencies: + "@discoveryjs/json-ext" "0.5.7" acorn "^8.0.4" acorn-walk "^8.0.0" - chalk "^4.1.0" commander "^7.2.0" + escape-string-regexp "^4.0.0" gzip-size "^6.0.0" - lodash "^4.17.20" + is-plain-object "^5.0.0" + lodash.debounce "^4.0.8" + lodash.escape "^4.0.1" + lodash.flatten "^4.4.0" + lodash.invokemap "^4.6.0" + lodash.pullall "^4.2.0" + lodash.uniqby "^4.7.0" opener "^1.5.2" - sirv "^1.0.7" + picocolors "^1.0.0" + sirv "^2.0.3" ws "^7.3.1" webpack-dev-middleware@^5.3.1: @@ -9915,9 +10209,9 @@ webpack-dev-middleware@^5.3.1: schema-utils "^4.0.0" webpack-dev-server@^4.9.3: - version "4.10.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.10.1.tgz#124ac9ac261e75303d74d95ab6712b4aec3e12ed" - integrity sha512-FIzMq3jbBarz3ld9l7rbM7m6Rj1lOsgq/DyLGMX/fPEB1UBUPtf5iL/4eNfhx8YYJTRlzfv107UfWSWcBK5Odw== + version "4.15.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz#8944b29c12760b3a45bdaa70799b17cb91b03df7" + integrity sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -9925,7 +10219,7 @@ webpack-dev-server@^4.9.3: "@types/serve-index" "^1.9.1" "@types/serve-static" "^1.13.10" "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.1" + "@types/ws" "^8.5.5" ansi-html-community "^0.0.8" bonjour-service "^1.0.11" chokidar "^3.5.3" @@ -9938,21 +10232,22 @@ webpack-dev-server@^4.9.3: html-entities "^2.3.2" http-proxy-middleware "^2.0.3" ipaddr.js "^2.0.1" + launch-editor "^2.6.0" open "^8.0.9" p-retry "^4.5.0" rimraf "^3.0.2" schema-utils "^4.0.0" - selfsigned "^2.0.1" + selfsigned "^2.1.1" serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" webpack-dev-middleware "^5.3.1" - ws "^8.4.2" + ws "^8.13.0" webpack-merge@^5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + version "5.9.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826" + integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg== dependencies: clone-deep "^4.0.1" wildcard "^2.0.0" @@ -9963,21 +10258,21 @@ webpack-sources@^3.2.2, webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.73.0: - version "5.74.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" - integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== + version "5.88.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" + integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" + acorn-import-assertions "^1.9.0" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.15.0" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" @@ -9986,9 +10281,9 @@ webpack@^5.73.0: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" + terser-webpack-plugin "^5.3.7" watchpack "^2.4.0" webpack-sources "^3.2.3" @@ -10016,6 +10311,18 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== +websocket@^1.0.34: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -10053,9 +10360,9 @@ widest-line@^4.0.1: string-width "^5.0.1" wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== wrap-ansi@^7.0.0: version "7.0.0" @@ -10067,9 +10374,9 @@ wrap-ansi@^7.0.0: strip-ansi "^6.0.0" wrap-ansi@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.0.1.tgz#2101e861777fec527d0ea90c57c6b03aac56a5b3" - integrity sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g== + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: ansi-styles "^6.1.0" string-width "^5.0.1" @@ -10096,14 +10403,14 @@ ws@7.4.5: integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g== "ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.3.1: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.4.2: - version "8.8.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" - integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== +ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== xdg-basedir@^4.0.0: version "4.0.0" @@ -10122,6 +10429,11 @@ xtend@^4.0.0, xtend@^4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" diff --git a/docs/actions/concepts.md b/docs/actions/concepts.md index 381f2551d22379..5b05a0c586a5d1 100644 --- a/docs/actions/concepts.md +++ b/docs/actions/concepts.md @@ -40,7 +40,11 @@ The Actions Framework consists of a few core concepts-- Each of these will be described in detail below. -![](imgs/actions.png) + +

+ +

+ **In the Actions Framework, Events flow continuously from left-to-right.** ### Pipelines diff --git a/docs/advanced/db-retention.md b/docs/advanced/db-retention.md index 91c7e2f0d3adc9..f154609a5ab2fe 100644 --- a/docs/advanced/db-retention.md +++ b/docs/advanced/db-retention.md @@ -38,8 +38,8 @@ We are planning to support a cron-based application of retention in the near fut ## How to configure? -For the initial iteration, we have made this feature opt-in. Please set **ENTITY_SERVICE_ENABLE_RETENTION=true** when -creating the datahub-gms container/k8s pod. +We have enabled with feature by default. Please set **ENTITY_SERVICE_ENABLE_RETENTION=false** when +creating the datahub-gms container/k8s pod to prevent the retention policies from taking effect. On GMS start up, retention policies are initialized with: 1. First, the default provided **version-based** retention to keep **20 latest aspects** for all entity-aspect pairs. diff --git a/docs/advanced/no-code-modeling.md b/docs/advanced/no-code-modeling.md index 9c8f6761a62bcb..172e63f821eabd 100644 --- a/docs/advanced/no-code-modeling.md +++ b/docs/advanced/no-code-modeling.md @@ -100,10 +100,9 @@ Currently, there are various models in GMS: 1. [Urn](https://github.com/datahub-project/datahub/blob/master/li-utils/src/main/pegasus/com/linkedin/common/DatasetUrn.pdl) - Structs composing primary keys 2. [Root] [Snapshots](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/metadata/snapshot/Snapshot.pdl) - Container of aspects 3. [Aspects](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/metadata/aspect/DashboardAspect.pdl) - Optional container of fields -4. [Values](https://github.com/datahub-project/datahub/blob/master/gms/api/src/main/pegasus/com/linkedin/dataset/Dataset.pdl), [Keys](https://github.com/datahub-project/datahub/blob/master/gms/api/src/main/pegasus/com/linkedin/dataset/DatasetKey.pdl) - Model returned by GMS [Rest.li](http://rest.li) API (public facing) -5. [Entities](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/metadata/entity/DatasetEntity.pdl) - Records with fields derived from the URN. Used only in graph / relationships -6. [Relationships](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/metadata/relationship/Relationship.pdl) - Edges between 2 entities with optional edge properties -7. [Search Documents](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/metadata/search/ChartDocument.pdl) - Flat documents for indexing within Elastic index +4. [Keys](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/metadata/key/DatasetKey.pdl) - Model returned by GMS [Rest.li](http://rest.li) API (public facing) +5. [Relationships](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/common/EntityRelationship.pdl) - Edges between 2 entities with optional edge properties +6. Search Documents - Flat documents for indexing within Elastic index - And corresponding index [mappings.json](https://github.com/datahub-project/datahub/blob/master/gms/impl/src/main/resources/index/chart/mappings.json), [settings.json](https://github.com/datahub-project/datahub/blob/master/gms/impl/src/main/resources/index/chart/settings.json) Various components of GMS depend on / make assumptions about these model types: @@ -159,11 +158,19 @@ along with simplifying the number of raw data models that need defined, includin From an architectural PoV, we will move from a before that looks something like this: -![no-code-before](../imgs/no-code-before.png) + +

+ +

+ to an after that looks like this -![no-code-after](../imgs/no-code-after.png) + +

+ +

+ That is, a move away from patterns of strong-typing-everywhere to a more generic + flexible world. diff --git a/docs/api/graphql/how-to-set-up-graphql.md b/docs/api/graphql/how-to-set-up-graphql.md index 562e8edb9f5d9d..2be2f935b12b10 100644 --- a/docs/api/graphql/how-to-set-up-graphql.md +++ b/docs/api/graphql/how-to-set-up-graphql.md @@ -62,9 +62,13 @@ Postman is a popular API client that provides a graphical user interface for sen Within Postman, you can create a `POST` request and set the request URL to the `/api/graphql` endpoint. In the request body, select the `GraphQL` option and enter your GraphQL query in the request body. -![postman-graphql](../../imgs/apis/postman-graphql.png) -Please refer to [Querying with GraphQL](https://learning.postman.com/docs/sending-requests/graphql/graphql/) in the Postman documentation for more information. +

+ +

+ + +Please refer to [Querying with GraphQL](https://learning.postman.com/docs/sending-requests/graphql/graphql-overview/) in the Postman documentation for more information. ### Authentication + Authorization diff --git a/docs/api/restli/evaluate-tests.md b/docs/api/restli/evaluate-tests.md index 3e4b6d73928a4d..5b466a5f429d4b 100644 --- a/docs/api/restli/evaluate-tests.md +++ b/docs/api/restli/evaluate-tests.md @@ -14,5 +14,5 @@ curl --location --request POST 'https://DOMAIN.acryl.io/gms/test?action=evaluate w The supported parameters are - `urn` - Required URN string -- `shouldPush` - Optional Boolean - whether or not to push the results to persist them +- `push` - Optional Boolean - whether or not to push the results to persist them. Default `false`. - `testUrns` - Optional List of string - If you wish to get specific test URNs evaluated diff --git a/docs/api/tutorials/custom-properties.md b/docs/api/tutorials/custom-properties.md index dbc07bfaa712ee..fe0d7e62dcde83 100644 --- a/docs/api/tutorials/custom-properties.md +++ b/docs/api/tutorials/custom-properties.md @@ -34,7 +34,11 @@ In this example, we will add some custom properties `cluster_name` and `retentio After you have ingested sample data, the dataset `fct_users_deleted` should have a custom properties section with `encoding` set to `utf-8`. -![dataset-properties-before](../../imgs/apis/tutorials/dataset-properties-before.png) + +

+ +

+ ```shell datahub get --urn "urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_deleted,PROD)" --aspect datasetProperties @@ -80,7 +84,11 @@ The following code adds custom properties `cluster_name` and `retention_time` to You can now see the two new properties are added to `fct_users_deleted` and the previous property `encoding` is unchanged. -![dataset-properties-added](../../imgs/apis/tutorials/dataset-properties-added.png) + +

+ +

+ We can also verify this operation by programmatically checking the `datasetProperties` aspect after running this code using the `datahub` cli. @@ -130,7 +138,11 @@ The following code shows you how can add and remove custom properties in the sam You can now see the `cluster_name` property is added to `fct_users_deleted` and the `retention_time` property is removed. -![dataset-properties-added-removed](../../imgs/apis/tutorials/dataset-properties-added-removed.png) + +

+ +

+ We can also verify this operation programmatically by checking the `datasetProperties` aspect using the `datahub` cli. @@ -179,7 +191,11 @@ The following code replaces the current custom properties with a new properties You can now see the `cluster_name` and `retention_time` properties are added to `fct_users_deleted` but the previous `encoding` property is no longer present. -![dataset-properties-replaced](../../imgs/apis/tutorials/dataset-properties-replaced.png) + +

+ +

+ We can also verify this operation programmatically by checking the `datasetProperties` aspect using the `datahub` cli. diff --git a/docs/api/tutorials/datasets.md b/docs/api/tutorials/datasets.md index 62b30e97c80202..7c6d4a88d4190e 100644 --- a/docs/api/tutorials/datasets.md +++ b/docs/api/tutorials/datasets.md @@ -42,7 +42,11 @@ For detailed steps, please refer to [Datahub Quickstart Guide](/docs/quickstart. You can now see `realestate_db.sales` dataset has been created. -![dataset-created](../../imgs/apis/tutorials/dataset-created.png) + +

+ +

+ ## Delete Dataset @@ -110,4 +114,8 @@ Expected Response: The dataset `fct_users_deleted` has now been deleted, so if you search for a hive dataset named `fct_users_delete`, you will no longer be able to see it. -![dataset-deleted](../../imgs/apis/tutorials/dataset-deleted.png) + +

+ +

+ diff --git a/docs/api/tutorials/deprecation.md b/docs/api/tutorials/deprecation.md index 6a8f7c8a1d2bed..73e73f5224cbc1 100644 --- a/docs/api/tutorials/deprecation.md +++ b/docs/api/tutorials/deprecation.md @@ -155,4 +155,8 @@ Expected Response: You can now see the dataset `fct_users_created` has been marked as `Deprecated.` -![tag-removed](../../imgs/apis/tutorials/deprecation-updated.png) + +

+ +

+ diff --git a/docs/api/tutorials/descriptions.md b/docs/api/tutorials/descriptions.md index 46f42b7a05be6a..27c57309ba76aa 100644 --- a/docs/api/tutorials/descriptions.md +++ b/docs/api/tutorials/descriptions.md @@ -275,7 +275,11 @@ Expected Response: You can now see the description is added to `fct_users_deleted`. -![dataset-description-added](../../imgs/apis/tutorials/dataset-description-added.png) + +

+ +

+ ## Add Description on Column @@ -357,4 +361,8 @@ Expected Response: You can now see column description is added to `user_name` column of `fct_users_deleted`. -![column-description-added](../../imgs/apis/tutorials/column-description-added.png) + +

+ +

+ diff --git a/docs/api/tutorials/domains.md b/docs/api/tutorials/domains.md index c8c47f85c570f8..617864d233b7a6 100644 --- a/docs/api/tutorials/domains.md +++ b/docs/api/tutorials/domains.md @@ -74,7 +74,11 @@ Expected Response: You can now see `Marketing` domain has been created under `Govern > Domains`. -![domain-created](../../imgs/apis/tutorials/domain-created.png) + +

+ +

+ ## Read Domains @@ -209,7 +213,11 @@ Expected Response: You can now see `Marketing` domain has been added to the dataset. -![domain-added](../../imgs/apis/tutorials/domain-added.png) + +

+ +

+ ## Remove Domains @@ -259,4 +267,8 @@ curl --location --request POST 'http://localhost:8080/api/graphql' \ You can now see a domain `Marketing` has been removed from the `fct_users_created` dataset. -![domain-removed](../../imgs/apis/tutorials/domain-removed.png) + +

+ +

+ diff --git a/docs/api/tutorials/lineage.md b/docs/api/tutorials/lineage.md index e37986af7bbbd4..dc43cb178f9498 100644 --- a/docs/api/tutorials/lineage.md +++ b/docs/api/tutorials/lineage.md @@ -112,7 +112,11 @@ Expected Response: You can now see the lineage between `fct_users_deleted` and `logging_events`. -![lineage-added](../../imgs/apis/tutorials/lineage-added.png) + +

+ +

+ ## Add Column-level Lineage @@ -130,15 +134,19 @@ You can now see the lineage between `fct_users_deleted` and `logging_events`. You can now see the column-level lineage between datasets. Note that you have to enable `Show Columns` to be able to see the column-level lineage. -![column-level-lineage-added](../../imgs/apis/tutorials/column-level-lineage-added.png) + +

+ +

+ ## Read Lineage -```json -mutation searchAcrossLineage { +```graphql +query searchAcrossLineage { searchAcrossLineage( input: { query: "*" diff --git a/docs/api/tutorials/ml.md b/docs/api/tutorials/ml.md index b16f2669b30c74..cb77556d48ebf5 100644 --- a/docs/api/tutorials/ml.md +++ b/docs/api/tutorials/ml.md @@ -94,9 +94,17 @@ Please note that an MlModelGroup serves as a container for all the runs of a sin You can search the entities in DataHub UI. -![feature-table-created](../../imgs/apis/tutorials/feature-table-created.png) -![model-group-created](../../imgs/apis/tutorials/model-group-created.png) +

+ +

+ + + +

+ +

+ ## Read ML Entities @@ -499,6 +507,14 @@ Expected Response: (Note that this entity does not exist in the sample ingestion You can access to `Features` or `Group` Tab of each entity to view the added entities. -![feature-added-to-model](../../imgs/apis/tutorials/feature-added-to-model.png) -![model-group-added-to-model](../../imgs/apis/tutorials/model-group-added-to-model.png) +

+ +

+ + + +

+ +

+ diff --git a/docs/api/tutorials/owners.md b/docs/api/tutorials/owners.md index 3c7a46b136d76c..5bc3b95cb5631b 100644 --- a/docs/api/tutorials/owners.md +++ b/docs/api/tutorials/owners.md @@ -77,7 +77,11 @@ Update succeeded for urn urn:li:corpuser:datahub. ### Expected Outcomes of Upserting User You can see the user `The bar` has been created and the user `Datahub` has been updated under `Settings > Access > Users & Groups` -![user-upserted](../../imgs/apis/tutorials/user-upserted.png) + +

+ +

+ ## Upsert Group @@ -125,7 +129,11 @@ Update succeeded for group urn:li:corpGroup:foogroup@acryl.io. ### Expected Outcomes of Upserting Group You can see the group `Foo Group` has been created under `Settings > Access > Users & Groups` -![group-upserted](../../imgs/apis/tutorials/group-upserted.png) + +

+ +

+ ## Read Owners @@ -272,7 +280,11 @@ curl --location --request POST 'http://localhost:8080/api/graphql' \ You can now see `bfoo` has been added as an owner to the `fct_users_created` dataset. -![ownership-added](../../imgs/apis/tutorials/owner-added.png) + +

+ +

+ ## Remove Owners @@ -340,4 +352,8 @@ curl --location --request POST 'http://localhost:8080/api/graphql' \ You can now see `John Doe` has been removed as an owner from the `fct_users_created` dataset. -![ownership-removed](../../imgs/apis/tutorials/owner-removed.png) + +

+ +

+ diff --git a/docs/api/tutorials/tags.md b/docs/api/tutorials/tags.md index 2f80a833136c1a..b2234bf00bcb92 100644 --- a/docs/api/tutorials/tags.md +++ b/docs/api/tutorials/tags.md @@ -91,7 +91,11 @@ Expected Response: You can now see the new tag `Deprecated` has been created. -![tag-created](../../imgs/apis/tutorials/tag-created.png) + +

+ +

+ We can also verify this operation by programmatically searching `Deprecated` tag after running this code using the `datahub` cli. @@ -307,7 +311,11 @@ Expected Response: You can now see `Deprecated` tag has been added to `user_name` column. -![tag-added](../../imgs/apis/tutorials/tag-added.png) + +

+ +

+ We can also verify this operation programmatically by checking the `globalTags` aspect using the `datahub` cli. @@ -359,7 +367,11 @@ curl --location --request POST 'http://localhost:8080/api/graphql' \ You can now see `Deprecated` tag has been removed to `user_name` column. -![tag-removed](../../imgs/apis/tutorials/tag-removed.png) + +

+ +

+ We can also verify this operation programmatically by checking the `gloablTags` aspect using the `datahub` cli. diff --git a/docs/api/tutorials/terms.md b/docs/api/tutorials/terms.md index 207e14ea4afe87..99acf77d26ab04 100644 --- a/docs/api/tutorials/terms.md +++ b/docs/api/tutorials/terms.md @@ -95,7 +95,11 @@ Expected Response: You can now see the new term `Rate of Return` has been created. -![term-created](../../imgs/apis/tutorials/term-created.png) + +

+ +

+ We can also verify this operation by programmatically searching `Rate of Return` term after running this code using the `datahub` cli. @@ -289,7 +293,11 @@ Expected Response: You can now see `Rate of Return` term has been added to `user_name` column. -![term-added](../../imgs/apis/tutorials/term-added.png) + +

+ +

+ ## Remove Terms @@ -361,4 +369,8 @@ curl --location --request POST 'http://localhost:8080/api/graphql' \ You can now see `Rate of Return` term has been removed to `user_name` column. -![term-removed](../../imgs/apis/tutorials/term-removed.png) + +

+ +

+ diff --git a/docs/architecture/architecture.md b/docs/architecture/architecture.md index 6b76b995cc4275..20f18f09d949be 100644 --- a/docs/architecture/architecture.md +++ b/docs/architecture/architecture.md @@ -10,8 +10,16 @@ disparate tools & systems. The figures below describe the high-level architecture of DataHub. -![datahub-architecture](../imgs/datahub-architecture.png) -![Acryl DataHub System Architecture ](../managed-datahub/imgs/saas/DataHub-Architecture.png) + +

+ +

+ + +

+ +

+ For a more detailed look at the components that make up the Architecture, check out [Components](../components.md). diff --git a/docs/architecture/metadata-ingestion.md b/docs/architecture/metadata-ingestion.md index 2b60383319c684..abf8fc24d13856 100644 --- a/docs/architecture/metadata-ingestion.md +++ b/docs/architecture/metadata-ingestion.md @@ -6,7 +6,11 @@ title: "Ingestion Framework" DataHub supports an extremely flexible ingestion architecture that can support push, pull, asynchronous and synchronous models. The figure below describes all the options possible for connecting your favorite system to DataHub. -![Ingestion Architecture](../imgs/ingestion-architecture.png) + +

+ +

+ ## Metadata Change Proposal: The Center Piece diff --git a/docs/architecture/metadata-serving.md b/docs/architecture/metadata-serving.md index ada41179af4e0a..57194f49d5ea41 100644 --- a/docs/architecture/metadata-serving.md +++ b/docs/architecture/metadata-serving.md @@ -6,7 +6,11 @@ title: "Serving Tier" The figure below shows the high-level system diagram for DataHub's Serving Tier. -![datahub-serving](../imgs/datahub-serving.png) + +

+ +

+ The primary component is called [the Metadata Service](../../metadata-service) and exposes a REST API and a GraphQL API for performing CRUD operations on metadata. The service also exposes search and graph query API-s to support secondary-index style queries, full-text search queries as well as relationship queries like lineage. In addition, the [datahub-frontend](../../datahub-frontend) service expose a GraphQL API on top of the metadata graph. diff --git a/docs/authentication/README.md b/docs/authentication/README.md index 4034cb15cfd22b..f6eda887844863 100644 --- a/docs/authentication/README.md +++ b/docs/authentication/README.md @@ -31,7 +31,8 @@ When a user makes a request for Data within DataHub, the request is authenticate and programmatic calls to DataHub APIs. There are two types of tokens that are important: 1. **Session Tokens**: Generated for users of the DataHub web application. By default, having a duration of 24 hours. -These tokens are encoded and stored inside browser-side session cookies. +These tokens are encoded and stored inside browser-side session cookies. The duration a session token is valid for is configurable via the `AUTH_SESSION_TTL_HOURS` environment variable +on the datahub-frontend deployment. 2. **Personal Access Tokens**: These are tokens generated via the DataHub settings panel useful for interacting with DataHub APIs. They can be used to automate processes like enriching documentation, ownership, tags, and more on DataHub. Learn more about Personal Access Tokens [here](personal-access-tokens.md). diff --git a/docs/authentication/concepts.md b/docs/authentication/concepts.md index 715e94c7e03808..0940f86a805f19 100644 --- a/docs/authentication/concepts.md +++ b/docs/authentication/concepts.md @@ -11,7 +11,11 @@ We introduced a few important concepts to the Metadata Service to make authentic In following sections, we'll take a closer look at each individually. -![](../imgs/metadata-service-auth.png) + +

+ +

+ *High level overview of Metadata Service Authentication* ## What is an Actor? diff --git a/docs/authentication/guides/add-users.md b/docs/authentication/guides/add-users.md index f5dfc832010831..d380cacd6665e4 100644 --- a/docs/authentication/guides/add-users.md +++ b/docs/authentication/guides/add-users.md @@ -19,13 +19,13 @@ To do so, navigate to the **Users & Groups** section inside of Settings page. He do not have the correct privileges to invite users, this button will be disabled.

- +

To invite new users, simply share the link with others inside your organization.

- +

When a new user visits the link, they will be directed to a sign up screen where they can create their DataHub account. @@ -37,13 +37,13 @@ and click **Reset user password** inside the menu dropdown on the right hand sid `Manage User Credentials` [Platform Privilege](../../authorization/access-policies-guide.md) in order to reset passwords.

- +

To reset the password, simply share the password reset link with the user who needs to change their password. Password reset links expire after 24 hours.

- +

# Configuring Single Sign-On with OpenID Connect diff --git a/docs/authentication/guides/sso/configure-oidc-behind-proxy.md b/docs/authentication/guides/sso/configure-oidc-behind-proxy.md new file mode 100644 index 00000000000000..c998816e047359 --- /dev/null +++ b/docs/authentication/guides/sso/configure-oidc-behind-proxy.md @@ -0,0 +1,64 @@ +# Configuring Frontend to use a Proxy when communicating with SSO Provider +*Authored on 22/08/2023* + +The `datahub-frontend-react` server can be configured to use an http proxy when retrieving the openid-configuration. +This can be needed if your infrastructure is locked down and disallows connectivity by default, using proxies for fine-grained egress control. + +## Configure http proxy and non proxy hosts + +To do this, you will need to pass a set of environment variables to the datahub-frontend-react container (e.g. in the `docker-compose.yml` file or your kubernetes manifest). + +``` +HTTP_PROXY_HOST=host of your http proxy +HTTP_PROXY_PORT=port of your http proxy +HTTPS_PROXY_HOST=host of your http(s) proxy used for https connections (often the same as the http proxy) +HTTPS_PROXY_PORT=port of your http(s) proxy used for https connections (often the same as the http proxy) +HTTP_NON_PROXY_HOSTS=localhost|datahub-gms (or any other hosts that you would like to bypass the proxy for, delimited by pipe) +``` + +## Optional: provide custom truststore +If your upstream proxy performs SSL termination to inspect traffic, this will result in different (self-signed) certificates for HTTPS connections. +The default truststore used in the `datahub-frontend-react` docker image will not trust these kinds of connections. +To address this, you can copy or mount your own truststore (provided by the proxy or network administrators) into the docker container. + +Depending on your setup, you have a few options to achieve this: + +### Make truststore available in the frontend + +#### Option a) Build frontend docker image with your own truststore included + +To build a custom image for your frontend, with the certificates built-in, you can use the official frontend image as a base, then copy in your required files. + +Example Dockerfile: + +```dockerfile +FROM linkedin/datahub-frontend-react: +COPY /truststore-directory /certificates +``` + +Building this Dockerfile will result in your own custom docker image on your local machine. +You will then be able to tag it, publish it to your own registry, etc. + +#### Option b) Mount truststore from your host machine using a docker volume + +Adapt your docker-compose.yml to include a new volume mount in the `datahub-frontend-react` container + +```docker + datahub-frontend-react: + # ... + volumes: + # ... + - /truststore-directory:/certificates +``` + +### Reference new truststore + +Add the following environment values to the `datahub-frontend-react` container: + +``` +SSL_TRUSTSTORE_FILE=path/to/truststore.jks (e.g. /certificates) +SSL_TRUSTSTORE_TYPE=jks +SSL_TRUSTSTORE_PASSWORD=MyTruststorePassword +``` + +Once these steps are done, your frontend container will use the new truststore when validating SSL/HTTPS connections. diff --git a/docs/authentication/guides/sso/configure-oidc-react-azure.md b/docs/authentication/guides/sso/configure-oidc-react-azure.md index d1859579678821..177387327c0e8e 100644 --- a/docs/authentication/guides/sso/configure-oidc-react-azure.md +++ b/docs/authentication/guides/sso/configure-oidc-react-azure.md @@ -32,7 +32,11 @@ Azure supports more than one redirect URI, so both can be configured at the same At this point, your app registration should look like the following: -![azure-setup-app-registration](img/azure-setup-app-registration.png) + +

+ +

+ e. Click **Register**. @@ -40,7 +44,11 @@ e. Click **Register**. Once registration is done, you will land on the app registration **Overview** tab. On the left-side navigation bar, click on **Authentication** under **Manage** and add extra redirect URIs if need be (if you want to support both local testing and Azure deployments). -![azure-setup-authentication](img/azure-setup-authentication.png) + +

+ +

+ Click **Save**. @@ -51,7 +59,11 @@ Select **Client secrets**, then **New client secret**. Type in a meaningful des **IMPORTANT:** Copy the `value` of your newly create secret since Azure will never display its value afterwards. -![azure-setup-certificates-secrets](img/azure-setup-certificates-secrets.png) + +

+ +

+ ### 4. Configure API permissions @@ -66,7 +78,11 @@ Click on **Add a permission**, then from the **Microsoft APIs** tab select **Mic At this point, you should be looking at a screen like the following: -![azure-setup-api-permissions](img/azure-setup-api-permissions.png) + +

+ +

+ ### 5. Obtain Application (Client) ID diff --git a/docs/authentication/guides/sso/configure-oidc-react-google.md b/docs/authentication/guides/sso/configure-oidc-react-google.md index 474538097aae20..af62185e6e7872 100644 --- a/docs/authentication/guides/sso/configure-oidc-react-google.md +++ b/docs/authentication/guides/sso/configure-oidc-react-google.md @@ -31,7 +31,11 @@ Note that in order to complete this step you should be logged into a Google acco c. Fill out the details in the App Information & Domain sections. Make sure the 'Application Home Page' provided matches where DataHub is deployed at your organization. -![google-setup-1](img/google-setup-1.png) + +

+ +

+ Once you've completed this, **Save & Continue**. @@ -70,7 +74,11 @@ f. You will now receive a pair of values, a client id and a client secret. Bookm At this point, you should be looking at a screen like the following: -![google-setup-2](img/google-setup-2.png) + +

+ +

+ Success! diff --git a/docs/authentication/guides/sso/configure-oidc-react-okta.md b/docs/authentication/guides/sso/configure-oidc-react-okta.md index cfede999f1e700..320b887a28f163 100644 --- a/docs/authentication/guides/sso/configure-oidc-react-okta.md +++ b/docs/authentication/guides/sso/configure-oidc-react-okta.md @@ -69,8 +69,16 @@ for example, `https://dev-33231928.okta.com/.well-known/openid-configuration`. At this point, you should be looking at a screen like the following: -![okta-setup-1](img/okta-setup-1.png) -![okta-setup-2](img/okta-setup-2.png) + +

+ +

+ + +

+ +

+ Success! @@ -96,7 +104,11 @@ Replacing the placeholders above with the client id & client secret received fro > > By default, we assume that the groups will appear in a claim named "groups". This can be customized using the `AUTH_OIDC_GROUPS_CLAIM` container configuration. > -> ![okta-setup-2](img/okta-setup-groups-claim.png) +> +

+ +

+ ### 5. Restart `datahub-frontend-react` docker container diff --git a/docs/authentication/guides/sso/configure-oidc-react.md b/docs/authentication/guides/sso/configure-oidc-react.md index b7efb94f842d62..512d6adbf916fc 100644 --- a/docs/authentication/guides/sso/configure-oidc-react.md +++ b/docs/authentication/guides/sso/configure-oidc-react.md @@ -26,7 +26,7 @@ please see [this guide](../jaas.md) to mount a custom user.props file for a JAAS To configure OIDC in React, you will most often need to register yourself as a client with your identity provider (Google, Okta, etc). Each provider may have their own instructions. Provided below are links to examples for Okta, Google, Azure AD, & Keycloak. -- [Registering an App in Okta](https://developer.okta.com/docs/guides/add-an-external-idp/apple/register-app-in-okta/) +- [Registering an App in Okta](https://developer.okta.com/docs/guides/add-an-external-idp/openidconnect/main/) - [OpenID Connect in Google Identity](https://developers.google.com/identity/protocols/oauth2/openid-connect) - [OpenID Connect authentication with Azure Active Directory](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/auth-oidc) - [Keycloak - Securing Applications and Services Guide](https://www.keycloak.org/docs/latest/securing_apps/) @@ -72,6 +72,7 @@ AUTH_OIDC_BASE_URL=your-datahub-url - `AUTH_OIDC_CLIENT_SECRET`: Unique client secret received from identity provider - `AUTH_OIDC_DISCOVERY_URI`: Location of the identity provider OIDC discovery API. Suffixed with `.well-known/openid-configuration` - `AUTH_OIDC_BASE_URL`: The base URL of your DataHub deployment, e.g. https://yourorgdatahub.com (prod) or http://localhost:9002 (testing) +- `AUTH_SESSION_TTL_HOURS`: The length of time in hours before a user will be prompted to login again. Session tokens are stateless so this determines at what time a session token may no longer be used and a valid session token can be used until this time has passed. Providing these configs will cause DataHub to delegate authentication to your identity provider, requesting the "oidc email profile" scopes and parsing the "preferred_username" claim from diff --git a/docs/authentication/guides/sso/img/azure-setup-api-permissions.png b/docs/authentication/guides/sso/img/azure-setup-api-permissions.png deleted file mode 100755 index 4964b7d48ffec2..00000000000000 Binary files a/docs/authentication/guides/sso/img/azure-setup-api-permissions.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/azure-setup-app-registration.png b/docs/authentication/guides/sso/img/azure-setup-app-registration.png deleted file mode 100755 index ffb23a7e3ddec5..00000000000000 Binary files a/docs/authentication/guides/sso/img/azure-setup-app-registration.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/azure-setup-authentication.png b/docs/authentication/guides/sso/img/azure-setup-authentication.png deleted file mode 100755 index 2d27ec88fb40b9..00000000000000 Binary files a/docs/authentication/guides/sso/img/azure-setup-authentication.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/azure-setup-certificates-secrets.png b/docs/authentication/guides/sso/img/azure-setup-certificates-secrets.png deleted file mode 100755 index db6585d84d8eeb..00000000000000 Binary files a/docs/authentication/guides/sso/img/azure-setup-certificates-secrets.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/google-setup-1.png b/docs/authentication/guides/sso/img/google-setup-1.png deleted file mode 100644 index 88c674146f1e44..00000000000000 Binary files a/docs/authentication/guides/sso/img/google-setup-1.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/google-setup-2.png b/docs/authentication/guides/sso/img/google-setup-2.png deleted file mode 100644 index 850512b891d5f3..00000000000000 Binary files a/docs/authentication/guides/sso/img/google-setup-2.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/okta-setup-1.png b/docs/authentication/guides/sso/img/okta-setup-1.png deleted file mode 100644 index 3949f18657c5ec..00000000000000 Binary files a/docs/authentication/guides/sso/img/okta-setup-1.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/okta-setup-2.png b/docs/authentication/guides/sso/img/okta-setup-2.png deleted file mode 100644 index fa6ea4d9918948..00000000000000 Binary files a/docs/authentication/guides/sso/img/okta-setup-2.png and /dev/null differ diff --git a/docs/authentication/guides/sso/img/okta-setup-groups-claim.png b/docs/authentication/guides/sso/img/okta-setup-groups-claim.png deleted file mode 100644 index ed35426685e467..00000000000000 Binary files a/docs/authentication/guides/sso/img/okta-setup-groups-claim.png and /dev/null differ diff --git a/docs/authentication/personal-access-tokens.md b/docs/authentication/personal-access-tokens.md index 0188aab49444ea..dc57a989a4e0c8 100644 --- a/docs/authentication/personal-access-tokens.md +++ b/docs/authentication/personal-access-tokens.md @@ -71,7 +71,11 @@ curl 'http://localhost:8080/entities/urn:li:corpuser:datahub' -H 'Authorization: Since authorization happens at the GMS level, this means that ingestion is also protected behind access tokens, to use them simply add a `token` to the sink config property as seen below: -![](../imgs/ingestion-with-token.png) + +

+ +

+ :::note diff --git a/docs/authorization/access-policies-guide.md b/docs/authorization/access-policies-guide.md index 5820e513a83e30..1eabb64d2878f6 100644 --- a/docs/authorization/access-policies-guide.md +++ b/docs/authorization/access-policies-guide.md @@ -110,10 +110,13 @@ In the second step, we can simply select the Privileges that this Platform Polic | Manage Tags | Allow the actor to create and remove any Tags | | Manage Public Views | Allow the actor to create, edit, and remove any public (shared) Views. | | Manage Ownership Types | Allow the actor to create, edit, and remove any Ownership Types. | +| Manage Platform Settings | (Acryl DataHub only) Allow the actor to manage global integrations and notification settings | +| Manage Monitors | (Acryl DataHub only) Allow the actor to create, remove, start, or stop any entity assertion monitors | | Restore Indices API[^1] | Allow the actor to restore indices for a set of entities via API | | Enable/Disable Writeability API[^1] | Allow the actor to enable or disable GMS writeability for use in data migrations | | Apply Retention API[^1] | Allow the actor to apply aspect retention via API | + [^1]: Only active if REST_API_AUTHORIZATION_ENABLED environment flag is enabled #### Step 3: Choose Policy Actors @@ -204,8 +207,15 @@ The common Metadata Privileges, which span across entity types, include: | Edit Status | Allow actor to edit the status of an entity (soft deleted or not). | | Edit Domain | Allow actor to edit the Domain of an entity. | | Edit Deprecation | Allow actor to edit the Deprecation status of an entity. | -| Edit Assertions | Allow actor to add and remove assertions from an entity. | -| Edit All | Allow actor to edit any information about an entity. Super user privileges. Controls the ability to ingest using API when REST API Authorization is enabled. | +| Edit Lineage | Allow actor to edit custom lineage edges for the entity. | +| Edit Data Product | Allow actor to edit the data product that an entity is part of | +| Propose Tags | (Acryl DataHub only) Allow actor to propose new Tags for the entity. | +| Propose Glossary Terms | (Acryl DataHub only) Allow actor to propose new Glossary Terms for the entity. | +| Propose Documentation | (Acryl DataHub only) Allow actor to propose new Documentation for the entity. | +| Manage Tag Proposals | (Acryl DataHub only) Allow actor to accept or reject proposed Tags for the entity. | +| Manage Glossary Terms Proposals | (Acryl DataHub only) Allow actor to accept or reject proposed Glossary Terms for the entity. | +| Manage Documentation Proposals | (Acryl DataHub only) Allow actor to accept or reject proposed Documentation for the entity | +| Edit Entity | Allow actor to edit any information about an entity. Super user privileges. Controls the ability to ingest using API when REST API Authorization is enabled. | | Get Timeline API[^1] | Allow actor to get the timeline of an entity via API. | | Get Entity API[^1] | Allow actor to get an entity via API. | | Get Timeseries Aspect API[^1] | Allow actor to get a timeseries aspect via API. | @@ -225,10 +235,19 @@ The common Metadata Privileges, which span across entity types, include: | Dataset | Edit Dataset Queries | Allow actor to edit the Highlighted Queries on the Queries tab of the dataset. | | Dataset | View Dataset Usage | Allow actor to access usage metadata about a dataset both in the UI and in the GraphQL API. This includes example queries, number of queries, etc. Also applies to REST APIs when REST API Authorization is enabled. | | Dataset | View Dataset Profile | Allow actor to access a dataset's profile both in the UI and in the GraphQL API. This includes snapshot statistics like #rows, #columns, null percentage per field, etc. | +| Dataset | Edit Assertions | Allow actor to change the assertions associated with a dataset. | +| Dataset | Edit Incidents | (Acryl DataHub only) Allow actor to change the incidents associated with a dataset. | +| Dataset | Edit Monitors | (Acryl DataHub only) Allow actor to change the assertion monitors associated with a dataset. | | Tag | Edit Tag Color | Allow actor to change the color of a Tag. | | Group | Edit Group Members | Allow actor to add and remove members to a group. | +| Group | Edit Contact Information | Allow actor to change email, slack handle associated with the group. | +| Group | Manage Group Subscriptions | (Acryl DataHub only) Allow actor to subscribe the group to entities. | +| Group | Manage Group Notifications | (Acryl DataHub only) Allow actor to change notification settings for the group. | | User | Edit User Profile | Allow actor to change the user's profile including display name, bio, title, profile image, etc. | | User + Group | Edit Contact Information | Allow actor to change the contact information such as email & chat handles. | +| Term Group | Manage Direct Glossary Children | Allow actor to change the direct child Term Groups or Terms of the group. | +| Term Group | Manage All Glossary Children | Allow actor to change any direct or indirect child Term Groups or Terms of the group. | + > **Still have questions about Privileges?** Let us know in [Slack](https://slack.datahubproject.io)! diff --git a/docs/cli.md b/docs/cli.md index eb8bb406b01074..267f289d9f54a6 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -547,7 +547,7 @@ Old Entities Migrated = {'urn:li:dataset:(urn:li:dataPlatform:hive,logging_event ### Using docker [![Docker Hub](https://img.shields.io/docker/pulls/acryldata/datahub-ingestion?style=plastic)](https://hub.docker.com/r/acryldata/datahub-ingestion) -[![datahub-ingestion docker](https://github.com/acryldata/datahub/actions/workflows/docker-ingestion.yml/badge.svg)](https://github.com/acryldata/datahub/actions/workflows/docker-ingestion.yml) +[![datahub-ingestion docker](https://github.com/acryldata/datahub/workflows/datahub-ingestion%20docker/badge.svg)](https://github.com/acryldata/datahub/actions/workflows/docker-ingestion.yml) If you don't want to install locally, you can alternatively run metadata ingestion within a Docker container. We have prebuilt images available on [Docker hub](https://hub.docker.com/r/acryldata/datahub-ingestion). All plugins will be installed and enabled automatically. diff --git a/docs/components.md b/docs/components.md index ef76729bb37fbf..b59dabcf999cce 100644 --- a/docs/components.md +++ b/docs/components.md @@ -6,7 +6,11 @@ title: "Components" The DataHub platform consists of the components shown in the following diagram. -![DataHub Component Overview](./imgs/datahub-components.png) + +

+ +

+ ## Metadata Store diff --git a/docs/demo/DataHub-UIOverview.pdf b/docs/demo/DataHub-UIOverview.pdf deleted file mode 100644 index cd6106e84ac236..00000000000000 Binary files a/docs/demo/DataHub-UIOverview.pdf and /dev/null differ diff --git a/docs/demo/DataHub_-_Powering_LinkedIn_Metadata.pdf b/docs/demo/DataHub_-_Powering_LinkedIn_Metadata.pdf deleted file mode 100644 index 71498045f9b5bf..00000000000000 Binary files a/docs/demo/DataHub_-_Powering_LinkedIn_Metadata.pdf and /dev/null differ diff --git a/docs/demo/Data_Discoverability_at_SpotHero.pdf b/docs/demo/Data_Discoverability_at_SpotHero.pdf deleted file mode 100644 index 83e37d8606428a..00000000000000 Binary files a/docs/demo/Data_Discoverability_at_SpotHero.pdf and /dev/null differ diff --git a/docs/demo/Datahub_-_Strongly_Consistent_Secondary_Indexing.pdf b/docs/demo/Datahub_-_Strongly_Consistent_Secondary_Indexing.pdf deleted file mode 100644 index 2d6a33a464650e..00000000000000 Binary files a/docs/demo/Datahub_-_Strongly_Consistent_Secondary_Indexing.pdf and /dev/null differ diff --git a/docs/demo/Datahub_at_Grofers.pdf b/docs/demo/Datahub_at_Grofers.pdf deleted file mode 100644 index c29cece9e250ac..00000000000000 Binary files a/docs/demo/Datahub_at_Grofers.pdf and /dev/null differ diff --git a/docs/demo/Designing_the_next_generation_of_metadata_events_for_scale.pdf b/docs/demo/Designing_the_next_generation_of_metadata_events_for_scale.pdf deleted file mode 100644 index 0d067eef28d03b..00000000000000 Binary files a/docs/demo/Designing_the_next_generation_of_metadata_events_for_scale.pdf and /dev/null differ diff --git a/docs/demo/Metadata_Use-Cases_at_LinkedIn_-_Lightning_Talk.pdf b/docs/demo/Metadata_Use-Cases_at_LinkedIn_-_Lightning_Talk.pdf deleted file mode 100644 index 382754f863c8a3..00000000000000 Binary files a/docs/demo/Metadata_Use-Cases_at_LinkedIn_-_Lightning_Talk.pdf and /dev/null differ diff --git a/docs/demo/Saxo Bank Data Workbench.pdf b/docs/demo/Saxo Bank Data Workbench.pdf deleted file mode 100644 index c43480d32b8f24..00000000000000 Binary files a/docs/demo/Saxo Bank Data Workbench.pdf and /dev/null differ diff --git a/docs/demo/Taming the Data Beast Using DataHub.pdf b/docs/demo/Taming the Data Beast Using DataHub.pdf deleted file mode 100644 index d0062465d92200..00000000000000 Binary files a/docs/demo/Taming the Data Beast Using DataHub.pdf and /dev/null differ diff --git a/docs/demo/Town_Hall_Presentation_-_12-2020_-_UI_Development_Part_2.pdf b/docs/demo/Town_Hall_Presentation_-_12-2020_-_UI_Development_Part_2.pdf deleted file mode 100644 index fb7bd2b693e877..00000000000000 Binary files a/docs/demo/Town_Hall_Presentation_-_12-2020_-_UI_Development_Part_2.pdf and /dev/null differ diff --git a/docs/demo/ViasatMetadataJourney.pdf b/docs/demo/ViasatMetadataJourney.pdf deleted file mode 100644 index ccffd18a06d187..00000000000000 Binary files a/docs/demo/ViasatMetadataJourney.pdf and /dev/null differ diff --git a/docs/deploy/aws.md b/docs/deploy/aws.md index 7b01ffa02a7446..228fcb51d1a28f 100644 --- a/docs/deploy/aws.md +++ b/docs/deploy/aws.md @@ -201,7 +201,11 @@ Provision a MySQL database in AWS RDS that shares the VPC with the kubernetes cl the VPC of the kubernetes cluster. Once the database is provisioned, you should be able to see the following page. Take a note of the endpoint marked by the red box. -![AWS RDS](../imgs/aws/aws-rds.png) + +

+ +

+ First, add the DB password to kubernetes by running the following. @@ -234,7 +238,11 @@ Provision an elasticsearch domain running elasticsearch version 7.10 or above th cluster or has VPC peering set up between the VPC of the kubernetes cluster. Once the domain is provisioned, you should be able to see the following page. Take a note of the endpoint marked by the red box. -![AWS Elasticsearch Service](../imgs/aws/aws-elasticsearch.png) + +

+ +

+ Update the elasticsearch settings under global in the values.yaml as follows. @@ -330,7 +338,11 @@ Provision an MSK cluster that shares the VPC with the kubernetes cluster or has the kubernetes cluster. Once the domain is provisioned, click on the “View client information” button in the ‘Cluster Summary” section. You should see a page like below. Take a note of the endpoints marked by the red boxes. -![AWS MSK](../imgs/aws/aws-msk.png) + +

+ +

+ Update the kafka settings under global in the values.yaml as follows. diff --git a/docs/deploy/confluent-cloud.md b/docs/deploy/confluent-cloud.md index d93ffcceaecee1..794b55d4686bfb 100644 --- a/docs/deploy/confluent-cloud.md +++ b/docs/deploy/confluent-cloud.md @@ -24,7 +24,11 @@ decommissioned. To create the topics, navigate to your **Cluster** and click "Create Topic". Feel free to tweak the default topic configurations to match your preferences. -![CreateTopic](../imgs/confluent-create-topic.png) + +

+ +

+ ## Step 2: Configure DataHub Container to use Confluent Cloud Topics @@ -140,12 +144,20 @@ and another for the user info used for connecting to the schema registry. You'll select "Clients" -> "Configure new Java Client". You should see a page like the following: -![Config](../imgs/confluent-cloud-config.png) + +

+ +

+ You'll want to generate both a Kafka Cluster API Key & a Schema Registry key. Once you do so,you should see the config automatically populate with your new secrets: -![Config](../imgs/confluent-cloud-config-2.png) + +

+ +

+ You'll need to copy the values of `sasl.jaas.config` and `basic.auth.user.info` for the next step. diff --git a/docs/deploy/environment-vars.md b/docs/deploy/environment-vars.md index af4ae09c009fd0..0689db9b173310 100644 --- a/docs/deploy/environment-vars.md +++ b/docs/deploy/environment-vars.md @@ -19,7 +19,7 @@ DataHub works. | Variable | Default | Unit/Type | Components | Description | |------------------------------------|---------|-----------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ASYNC_INGESTION_DEFAULT` | `false` | boolean | [`GMS`] | Asynchronously process ingestProposals by writing the ingestion MCP to Kafka. Typically enabled with standalone consumers. | +| `ASYNC_INGEST_DEFAULT` | `false` | boolean | [`GMS`] | Asynchronously process ingestProposals by writing the ingestion MCP to Kafka. Typically enabled with standalone consumers. | | `MCP_CONSUMER_ENABLED` | `true` | boolean | [`GMS`, `MCE Consumer`] | When running in standalone mode, disabled on `GMS` and enabled on separate `MCE Consumer`. | | `MCL_CONSUMER_ENABLED` | `true` | boolean | [`GMS`, `MAE Consumer`] | When running in standalone mode, disabled on `GMS` and enabled on separate `MAE Consumer`. | | `PE_CONSUMER_ENABLED` | `true` | boolean | [`GMS`, `MAE Consumer`] | When running in standalone mode, disabled on `GMS` and enabled on separate `MAE Consumer`. | @@ -79,8 +79,9 @@ Simply replace the dot, `.`, with an underscore, `_`, and convert to uppercase. ## Frontend -| Variable | Default | Unit/Type | Components | Description | -|------------------------------------|----------|-----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------| -| `AUTH_VERBOSE_LOGGING` | `false` | boolean | [`Frontend`] | Enable verbose authentication logging. Enabling this will leak sensisitve information in the logs. Disable when finished debugging. | -| `AUTH_OIDC_GROUPS_CLAIM` | `groups` | string | [`Frontend`] | Claim to use as the user's group. | -| `AUTH_OIDC_EXTRACT_GROUPS_ENABLED` | `false` | boolean | [`Frontend`] | Auto-provision the group from the user's group claim. | +| Variable | Default | Unit/Type | Components | Description | +|------------------------------------|----------|-----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `AUTH_VERBOSE_LOGGING` | `false` | boolean | [`Frontend`] | Enable verbose authentication logging. Enabling this will leak sensisitve information in the logs. Disable when finished debugging. | +| `AUTH_OIDC_GROUPS_CLAIM` | `groups` | string | [`Frontend`] | Claim to use as the user's group. | +| `AUTH_OIDC_EXTRACT_GROUPS_ENABLED` | `false` | boolean | [`Frontend`] | Auto-provision the group from the user's group claim. | +| `AUTH_SESSION_TTL_HOURS` | `24` | string | [`Frontend`] | The number of hours a user session is valid. [User session tokens are stateless and will become invalid after this time](https://www.playframework.com/documentation/2.8.x/SettingsSession#Session-Timeout-/-Expiration) requiring a user to login again. | \ No newline at end of file diff --git a/docs/deploy/gcp.md b/docs/deploy/gcp.md index 3713d69f90636c..0cd3d92a8f3cd3 100644 --- a/docs/deploy/gcp.md +++ b/docs/deploy/gcp.md @@ -65,16 +65,28 @@ the GKE page on [GCP website](https://console.cloud.google.com/kubernetes/discov Once all deploy is successful, you should see a page like below in the "Services & Ingress" tab on the left. -![Services and Ingress](../imgs/gcp/services_ingress.png) + +

+ +

+ Tick the checkbox for datahub-datahub-frontend and click "CREATE INGRESS" button. You should land on the following page. -![Ingress1](../imgs/gcp/ingress1.png) + +

+ +

+ Type in an arbitrary name for the ingress and click on the second step "Host and path rules". You should land on the following page. -![Ingress2](../imgs/gcp/ingress2.png) + +

+ +

+ Select "datahub-datahub-frontend" in the dropdown menu for backends, and then click on "ADD HOST AND PATH RULE" button. In the second row that got created, add in the host name of choice (here gcp.datahubproject.io) and select @@ -83,14 +95,22 @@ In the second row that got created, add in the host name of choice (here gcp.dat This step adds the rule allowing requests from the host name of choice to get routed to datahub-frontend service. Click on step 3 "Frontend configuration". You should land on the following page. -![Ingress3](../imgs/gcp/ingress3.png) + +

+ +

+ Choose HTTPS in the dropdown menu for protocol. To enable SSL, you need to add a certificate. If you do not have one, you can click "CREATE A NEW CERTIFICATE" and input the host name of choice. GCP will create a certificate for you. Now press "CREATE" button on the left to create ingress! After around 5 minutes, you should see the following. -![Ingress Ready](../imgs/gcp/ingress_ready.png) + +

+ +

+ In your domain provider, add an A record for the host name set above using the IP address on the ingress page (noted with the red box). Once DNS updates, you should be able to access DataHub through the host name!! @@ -98,5 +118,9 @@ with the red box). Once DNS updates, you should be able to access DataHub throug Note, ignore the warning icon next to ingress. It takes about ten minutes for ingress to check that the backend service is ready and show a check mark as follows. However, ingress is fully functional once you see the above page. -![Ingress Final](../imgs/gcp/ingress_final.png) + +

+ +

+ diff --git a/docs/dev-guides/timeline.md b/docs/dev-guides/timeline.md index 966e659b909915..829aef1d3eefa1 100644 --- a/docs/dev-guides/timeline.md +++ b/docs/dev-guides/timeline.md @@ -14,7 +14,11 @@ The Timeline API is available in server versions `0.8.28` and higher. The `cli` ## Entity Timeline Conceptually For the visually inclined, here is a conceptual diagram that illustrates how to think about the entity timeline with categorical changes overlaid on it. -![../imgs/timeline/timeline-conceptually.png](../imgs/timeline/timeline-conceptually.png) + +

+ +

+ ## Change Event Each modification is modeled as a @@ -228,8 +232,16 @@ http://localhost:8080/openapi/timeline/v1/urn%3Ali%3Adataset%3A%28urn%3Ali%3Adat The API is browse-able via the UI through through the dropdown. Here are a few screenshots showing how to navigate to it. You can try out the API and send example requests. -![../imgs/timeline/dropdown-apis.png](../imgs/timeline/dropdown-apis.png) -![../imgs/timeline/swagger-ui.png](../imgs/timeline/swagger-ui.png) + +

+ +

+ + +

+ +

+ # Future Work diff --git a/docs/docker/development.md b/docs/docker/development.md index 2153aa9dc613f1..91a303744a03bd 100644 --- a/docs/docker/development.md +++ b/docs/docker/development.md @@ -92,7 +92,11 @@ Environment variables control the debugging ports for GMS and the frontend. The screenshot shows an example configuration for IntelliJ using the default GMS debugging port of 5001. -![](../imgs/development/intellij-remote-debug.png) + +

+ +

+ ## Tips for People New To Docker diff --git a/docs/domains.md b/docs/domains.md index c846a753417c59..1b2ebc9d47f397 100644 --- a/docs/domains.md +++ b/docs/domains.md @@ -22,20 +22,20 @@ You can create this privileges by creating a new [Metadata Policy](./authorizati To create a Domain, first navigate to the **Domains** tab in the top-right menu of DataHub.

- +

Once you're on the Domains page, you'll see a list of all the Domains that have been created on DataHub. Additionally, you can view the number of entities inside each Domain.

- +

To create a new Domain, click '+ New Domain'.

- +

Inside the form, you can choose a name for your Domain. Most often, this will align with your business units or groups, for example @@ -48,7 +48,7 @@ for the Domain. This option is useful if you intend to refer to Domains by a com key to be human-readable. Proceed with caution: once you select a custom id, it cannot be easily changed.

- +

By default, you don't need to worry about this. DataHub will auto-generate a unique Domain id for you. @@ -64,7 +64,7 @@ To assign an asset to a Domain, simply navigate to the asset's profile page. At see a 'Domain' section. Click 'Set Domain', and then search for the Domain you'd like to add to. When you're done, click 'Add'.

- +

To remove an asset from a Domain, click the 'x' icon on the Domain tag. @@ -149,27 +149,27 @@ source: Once you've created a Domain, you can use the search bar to find it.

- +

Clicking on the search result will take you to the Domain's profile, where you can edit its description, add / remove owners, and view the assets inside the Domain.

- +

Once you've added assets to a Domain, you can filter search results to limit to those Assets within a particular Domain using the left-side search filters.

- +

On the homepage, you'll also find a list of the most popular Domains in your organization.

- +

## Additional Resources @@ -242,7 +242,6 @@ DataHub supports Tags, Glossary Terms, & Domains as distinct types of Metadata t - **Tags**: Informal, loosely controlled labels that serve as a tool for search & discovery. Assets may have multiple tags. No formal, central management. - **Glossary Terms**: A controlled vocabulary, with optional hierarchy. Terms are typically used to standardize types of leaf-level attributes (i.e. schema fields) for governance. E.g. (EMAIL_PLAINTEXT) - **Domains**: A set of top-level categories. Usually aligned to business units / disciplines to which the assets are most relevant. Central or distributed management. Single Domain assignment per data asset. - *Need more help? Join the conversation in [Slack](http://slack.datahubproject.io)!* ### Related Features diff --git a/docs/glossary/business-glossary.md b/docs/glossary/business-glossary.md index faab6f12fc55e7..e10cbed30b9132 100644 --- a/docs/glossary/business-glossary.md +++ b/docs/glossary/business-glossary.md @@ -31,59 +31,103 @@ In order to view a Business Glossary, users must have the Platform Privilege cal Once granted this privilege, you can access your Glossary by clicking the dropdown at the top of the page called **Govern** and then click **Glossary**: -![](../imgs/glossary/glossary-button.png) + +

+ +

+ You are now at the root of your Glossary and should see all Terms and Term Groups with no parents assigned to them. You should also notice a hierarchy navigator on the left where you can easily check out the structure of your Glossary! -![](../imgs/glossary/root-glossary.png) + +

+ +

+ ## Creating a Term or Term Group There are two ways to create Terms and Term Groups through the UI. First, you can create directly from the Glossary home page by clicking the menu dots on the top right and selecting your desired option: -![](../imgs/glossary/root-glossary-create.png) + +

+ +

+ You can also create Terms or Term Groups directly from a Term Group's page. In order to do that you need to click the menu dots on the top right and select what you want: -![](../imgs/glossary/create-from-node.png) + +

+ +

+ Note that the modal that pops up will automatically set the current Term Group you are in as the **Parent**. You can easily change this by selecting the input and navigating through your Glossary to find your desired Term Group. In addition, you could start typing the name of a Term Group to see it appear by searching. You can also leave this input blank in order to create a Term or Term Group with no parent. -![](../imgs/glossary/create-modal.png) + +

+ +

+ ## Editing a Term or Term Group In order to edit a Term or Term Group, you first need to go the page of the Term or Term group you want to edit. Then simply click the edit icon right next to the name to open up an inline editor. Change the text and it will save when you click outside or hit Enter. -![](../imgs/glossary/edit-term.png) + +

+ +

+ ## Moving a Term or Term Group Once a Term or Term Group has been created, you can always move it to be under a different Term Group parent. In order to do this, click the menu dots on the top right of either entity and select **Move**. -![](../imgs/glossary/move-term-button.png) + +

+ +

+ This will open a modal where you can navigate through your Glossary to find your desired Term Group. -![](../imgs/glossary/move-term-modal.png) + +

+ +

+ ## Deleting a Term or Term Group In order to delete a Term or Term Group, you need to go to the entity page of what you want to delete then click the menu dots on the top right. From here you can select **Delete** followed by confirming through a separate modal. **Note**: at the moment we only support deleting Term Groups that do not have any children. Until cascade deleting is supported, you will have to delete all children first, then delete the Term Group. -![](../imgs/glossary/delete-button.png) + +

+ +

+ ## Adding a Term to an Entity Once you've defined your Glossary, you can begin attaching terms to data assets. To add a Glossary Term to an asset, go to the entity page of your asset and find the **Add Terms** button on the right sidebar. -![](../imgs/glossary/add-term-to-entity.png) + +

+ +

+ In the modal that pops up you can select the Term you care about in one of two ways: - Search for the Term by name in the input - Navigate through the Glossary dropdown that appears after clicking into the input -![](../imgs/glossary/add-term-modal.png) + +

+ +

+ ## Privileges diff --git a/docs/how/add-new-aspect.md b/docs/how/add-new-aspect.md index 6ea7256ed75cc0..d1fe567018903b 100644 --- a/docs/how/add-new-aspect.md +++ b/docs/how/add-new-aspect.md @@ -1,20 +1,20 @@ # How to add a new metadata aspect? Adding a new metadata [aspect](../what/aspect.md) is one of the most common ways to extend an existing [entity](../what/entity.md). -We'll use the [CorpUserEditableInfo](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/identity/CorpUserEditableInfo.pdl) as an example here. +We'll use the CorpUserEditableInfo as an example here. 1. Add the aspect model to the corresponding namespace (e.g. [`com.linkedin.identity`](https://github.com/datahub-project/datahub/tree/master/metadata-models/src/main/pegasus/com/linkedin/identity)) -2. Extend the entity's aspect union to include the new aspect (e.g. [`CorpUserAspect`](https://github.com/datahub-project/datahub/blob/master/metadata-models/src/main/pegasus/com/linkedin/metadata/aspect/CorpUserAspect.pdl)) +2. Extend the entity's aspect union to include the new aspect. 3. Rebuild the rest.li [IDL & snapshot](https://linkedin.github.io/rest.li/modeling/compatibility_check) by running the following command from the project root ``` ./gradlew :metadata-service:restli-servlet-impl:build -Prest.model.compatibility=ignore ``` -4. To surface the new aspect at the top-level [resource endpoint](https://linkedin.github.io/rest.li/user_guide/restli_server#writing-resources), extend the resource data model (e.g. [`CorpUser`](https://github.com/datahub-project/datahub/blob/master/gms/api/src/main/pegasus/com/linkedin/identity/CorpUser.pdl)) with an optional field (e.g. [`editableInfo`](https://github.com/datahub-project/datahub/blob/master/gms/api/src/main/pegasus/com/linkedin/identity/CorpUser.pdl#L21)). You'll also need to extend the `toValue` & `toSnapshot` methods of the top-level resource (e.g. [`CorpUsers`](https://github.com/datahub-project/datahub/blob/master/gms/impl/src/main/java/com/linkedin/metadata/resources/identity/CorpUsers.java)) to convert between the snapshot & value models. +4. To surface the new aspect at the top-level [resource endpoint](https://linkedin.github.io/rest.li/user_guide/restli_server#writing-resources), extend the resource data model with an optional field. You'll also need to extend the `toValue` & `toSnapshot` methods of the top-level resource (e.g. [`CorpUsers`](https://github.com/datahub-project/datahub/blob/master/gms/impl/src/main/java/com/linkedin/metadata/resources/identity/CorpUsers.java)) to convert between the snapshot & value models. -5. (Optional) If there's need to update the aspect via API (instead of/in addition to MCE), add a [sub-resource](https://linkedin.github.io/rest.li/user_guide/restli_server#sub-resources) endpoint for the new aspect (e.g. [`CorpUsersEditableInfoResource`](https://github.com/datahub-project/datahub/blob/master/gms/impl/src/main/java/com/linkedin/metadata/resources/identity/CorpUsersEditableInfoResource.java)). The sub-resource endpiont also allows you to retrieve previous versions of the aspect as well as additional metadata such as the audit stamp. +5. (Optional) If there's need to update the aspect via API (instead of/in addition to MCE), add a [sub-resource](https://linkedin.github.io/rest.li/user_guide/restli_server#sub-resources) endpoint for the new aspect (e.g. `CorpUsersEditableInfoResource`). The sub-resource endpiont also allows you to retrieve previous versions of the aspect as well as additional metadata such as the audit stamp. -6. After rebuilding & restarting [gms](https://github.com/datahub-project/datahub/tree/master/gms), [mce-consumer-job](https://github.com/datahub-project/datahub/tree/master/metadata-jobs/mce-consumer-job) & [mae-consumer-job](https://github.com/datahub-project/datahub/tree/master/metadata-jobs/mae-consumer-job), +6. After rebuilding & restarting gms, [mce-consumer-job](https://github.com/datahub-project/datahub/tree/master/metadata-jobs/mce-consumer-job) & [mae-consumer-job](https://github.com/datahub-project/datahub/tree/master/metadata-jobs/mae-consumer-job),z you should be able to start emitting [MCE](../what/mxe.md) with the new aspect and have it automatically ingested & stored in DB. diff --git a/docs/how/configuring-authorization-with-apache-ranger.md b/docs/how/configuring-authorization-with-apache-ranger.md index 26d3be6d358b2e..46f9432e6c18a7 100644 --- a/docs/how/configuring-authorization-with-apache-ranger.md +++ b/docs/how/configuring-authorization-with-apache-ranger.md @@ -67,7 +67,11 @@ Now, you should have the DataHub plugin registered with Apache Ranger. Next, we' **DATAHUB** plugin and **ranger_datahub** service is shown in below screenshot:
- ![Privacera Portal DATAHUB screenshot](../imgs/apache-ranger/datahub-plugin.png) + +

+ +

+ 4. Create a new policy under service **ranger_datahub** - this will be used to control DataHub authorization. 5. Create a test user & assign them to a policy. We'll use the `datahub` user, which is the default root user inside DataHub. @@ -80,7 +84,11 @@ Now, you should have the DataHub plugin registered with Apache Ranger. Next, we' DataHub platform access policy screenshot:
- ![Privacera Portal DATAHUB screenshot](../imgs/apache-ranger/datahub-platform-access-policy.png) + +

+ +

+ Once we've created our first policy, we can set up DataHub to start authorizing requests using Ranger policies. @@ -178,7 +186,11 @@ then follow the below sections to undo the configuration steps you have performe **ranger_datahub** service is shown in below screenshot:
- ![Privacera Portal DATAHUB screenshot](../imgs/apache-ranger/datahub-plugin.png) + +

+ +

+ 2. Delete **datahub** plugin: Execute below curl command to delete **datahub** plugin Replace variables with corresponding values in curl command diff --git a/docs/how/delete-metadata.md b/docs/how/delete-metadata.md index acbb573020be08..f720a66ce57652 100644 --- a/docs/how/delete-metadata.md +++ b/docs/how/delete-metadata.md @@ -43,6 +43,9 @@ datahub delete --platform snowflake # Filters can be combined, which will select entities that match all filters. datahub delete --platform looker --entity-type chart datahub delete --platform bigquery --env PROD + +# You can also do recursive deletes for container and dataPlatformInstance entities. +datahub delete --urn "urn:li:container:f76..." --recursive ``` When performing hard deletes, you can optionally add the `--only-soft-deleted` flag to only hard delete entities that were previously soft deleted. @@ -122,6 +125,14 @@ datahub delete --urn "urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_deleted datahub delete --platform snowflake --env DEV ``` +#### Delete everything within a specific Snowflake DB + +```shell +# You can find your container urn by navigating to the relevant +# DB in the DataHub UI and clicking the "copy urn" button. +datahub delete --urn "urn:li:container:77644901c4f574845578ebd18b7c14fa" --recursive +``` + #### Delete all BigQuery datasets in the PROD environment ```shell @@ -129,6 +140,13 @@ datahub delete --platform snowflake --env DEV datahub delete --env PROD --entity-type dataset --platform bigquery ``` +#### Delete everything within a MySQL platform instance + +```shell +# The instance name comes from the `platform_instance` config option in the ingestion recipe. +datahub delete --urn 'urn:li:dataPlatformInstance:(urn:li:dataPlatform:mysql,my_instance_name)' --recursive +``` + #### Delete all pipelines and tasks from Airflow ```shell @@ -138,6 +156,7 @@ datahub delete --platform "airflow" #### Delete all containers for a particular platform ```shell +# Note: this will leave S3 datasets intact. datahub delete --entity-type container --platform s3 ``` diff --git a/docs/how/search.md b/docs/how/search.md index bf1c8e8632e243..6a5e85e547fc50 100644 --- a/docs/how/search.md +++ b/docs/how/search.md @@ -2,14 +2,6 @@ import FeatureAvailability from '@site/src/components/FeatureAvailability'; # About DataHub Search - - - - The **search bar** is an important mechanism for discovering data assets in DataHub. From the search bar, you can find Datasets, Columns, Dashboards, Charts, Data Pipelines, and more. Simply type in a term and press 'enter'. diff --git a/docs/how/updating-datahub.md b/docs/how/updating-datahub.md index 2b6fd5571cc9ec..9b19291ee246ae 100644 --- a/docs/how/updating-datahub.md +++ b/docs/how/updating-datahub.md @@ -5,16 +5,42 @@ This file documents any backwards-incompatible changes in DataHub and assists pe ## Next ### Breaking Changes +- #8810 - Removed support for SQLAlchemy 1.3.x. Only SQLAlchemy 1.4.x is supported now. ### Potential Downtime +### Deprecations + +### Other Notable Changes + +## 0.11.0 + +### Breaking Changes + +### Potential Downtime +- #8611 Search improvements requires reindexing indices. A `system-update` job will run which will set indices to read-only and create a backup/clone of each index. During the reindexing new components will be prevented from start-up until the reindex completes. The logs of this job will indicate a % complete per index. Depending on index sizes and infrastructure this process can take 5 minutes to hours however as a rough estimate 1 hour for every 2.3 million entities. + ### Deprecations - #8525: In LDAP ingestor, the `manager_pagination_enabled` changed to general `pagination_enabled` +- MAE Events are no longer produced. MAE events have been deprecated for over a year. ### Other Notable Changes +- In this release we now enable you to create and delete pinned announcements on your DataHub homepage! If you have the “Manage Home Page Posts” platform privilege you’ll see a new section in settings called “Home Page Posts” where you can create and delete text posts and link posts that your users see on the home page. +- The new search and browse experience, which was first made available in the previous release behind a feature flag, is now on by default. Check out our release notes for v0.10.5 to get more information and documentation on this new Browse experience. +- In addition to the ranking changes mentioned above, this release includes changes to the highlighting of search entities to understand why they match your query. You can also sort your results alphabetically or by last updated times, in addition to relevance. In this release, we suggest a correction if your query has a typo in it. - #8300: Clickhouse source now inherited from TwoTierSQLAlchemy. In old way we have platform_instance -> container -> co container db (None) -> container schema and now we have platform_instance -> container database. - #8300: Added `uri_opts` argument; now we can add any options for clickhouse client. +- #8659: BigQuery ingestion no longer creates DataPlatformInstance aspects by default. + This will only affect users that were depending on this aspect for custom functionality, + and can be enabled via the `include_data_platform_instance` config option. +- OpenAPI entity and aspect endpoints expanded to improve developer experience when using this API with additional aspects to be added in the near future. +- The CLI now supports recursive deletes. +- Batching of default aspects on initial ingestion (SQL) +- Improvements to multi-threading. Ingestion recipes, if previously reduced to 1 thread, can be restored to the 15 thread default. +- Gradle 7 upgrade moderately improves build speed +- DataHub Ingestion slim images reduced in size by 2GB+ +- Glue Schema Registry fixed ## 0.10.5 diff --git a/docs/imgs/add-schema-tag.png b/docs/imgs/add-schema-tag.png deleted file mode 100644 index b6fd273389c904..00000000000000 Binary files a/docs/imgs/add-schema-tag.png and /dev/null differ diff --git a/docs/imgs/add-tag-search.png b/docs/imgs/add-tag-search.png deleted file mode 100644 index a129f5eba4271b..00000000000000 Binary files a/docs/imgs/add-tag-search.png and /dev/null differ diff --git a/docs/imgs/add-tag.png b/docs/imgs/add-tag.png deleted file mode 100644 index 386b4cdcd99113..00000000000000 Binary files a/docs/imgs/add-tag.png and /dev/null differ diff --git a/docs/imgs/added-tag.png b/docs/imgs/added-tag.png deleted file mode 100644 index 96ae48318a35a1..00000000000000 Binary files a/docs/imgs/added-tag.png and /dev/null differ diff --git a/docs/imgs/airflow/connection_error.png b/docs/imgs/airflow/connection_error.png deleted file mode 100644 index c2f3344b8cc452..00000000000000 Binary files a/docs/imgs/airflow/connection_error.png and /dev/null differ diff --git a/docs/imgs/airflow/datahub_lineage_view.png b/docs/imgs/airflow/datahub_lineage_view.png deleted file mode 100644 index c7c774c203d2f2..00000000000000 Binary files a/docs/imgs/airflow/datahub_lineage_view.png and /dev/null differ diff --git a/docs/imgs/airflow/datahub_pipeline_entity.png b/docs/imgs/airflow/datahub_pipeline_entity.png deleted file mode 100644 index 715baefd784ca4..00000000000000 Binary files a/docs/imgs/airflow/datahub_pipeline_entity.png and /dev/null differ diff --git a/docs/imgs/airflow/datahub_pipeline_view.png b/docs/imgs/airflow/datahub_pipeline_view.png deleted file mode 100644 index 5b3afd13c4ce69..00000000000000 Binary files a/docs/imgs/airflow/datahub_pipeline_view.png and /dev/null differ diff --git a/docs/imgs/airflow/datahub_task_view.png b/docs/imgs/airflow/datahub_task_view.png deleted file mode 100644 index 66b3487d87319d..00000000000000 Binary files a/docs/imgs/airflow/datahub_task_view.png and /dev/null differ diff --git a/docs/imgs/airflow/entity_page_screenshot.png b/docs/imgs/airflow/entity_page_screenshot.png deleted file mode 100644 index a782969a1f17b1..00000000000000 Binary files a/docs/imgs/airflow/entity_page_screenshot.png and /dev/null differ diff --git a/docs/imgs/airflow/find_the_dag.png b/docs/imgs/airflow/find_the_dag.png deleted file mode 100644 index 37cda041e4b750..00000000000000 Binary files a/docs/imgs/airflow/find_the_dag.png and /dev/null differ diff --git a/docs/imgs/airflow/finding_failed_log.png b/docs/imgs/airflow/finding_failed_log.png deleted file mode 100644 index 96552ba1e19839..00000000000000 Binary files a/docs/imgs/airflow/finding_failed_log.png and /dev/null differ diff --git a/docs/imgs/airflow/paused_dag.png b/docs/imgs/airflow/paused_dag.png deleted file mode 100644 index c314de5d38d750..00000000000000 Binary files a/docs/imgs/airflow/paused_dag.png and /dev/null differ diff --git a/docs/imgs/airflow/successful_run.png b/docs/imgs/airflow/successful_run.png deleted file mode 100644 index b997cc7210ff6b..00000000000000 Binary files a/docs/imgs/airflow/successful_run.png and /dev/null differ diff --git a/docs/imgs/airflow/trigger_dag.png b/docs/imgs/airflow/trigger_dag.png deleted file mode 100644 index a44999c929d4e2..00000000000000 Binary files a/docs/imgs/airflow/trigger_dag.png and /dev/null differ diff --git a/docs/imgs/airflow/unpaused_dag.png b/docs/imgs/airflow/unpaused_dag.png deleted file mode 100644 index 8462562f31d973..00000000000000 Binary files a/docs/imgs/airflow/unpaused_dag.png and /dev/null differ diff --git a/docs/imgs/apache-ranger/datahub-platform-access-policy.png b/docs/imgs/apache-ranger/datahub-platform-access-policy.png deleted file mode 100644 index 7e3ff6fd372a9d..00000000000000 Binary files a/docs/imgs/apache-ranger/datahub-platform-access-policy.png and /dev/null differ diff --git a/docs/imgs/apache-ranger/datahub-plugin.png b/docs/imgs/apache-ranger/datahub-plugin.png deleted file mode 100644 index 5dd044c0146570..00000000000000 Binary files a/docs/imgs/apache-ranger/datahub-plugin.png and /dev/null differ diff --git a/docs/imgs/apis/postman-graphql.png b/docs/imgs/apis/postman-graphql.png deleted file mode 100644 index 1cffd226fdf772..00000000000000 Binary files a/docs/imgs/apis/postman-graphql.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/column-description-added.png b/docs/imgs/apis/tutorials/column-description-added.png deleted file mode 100644 index ed8cbd3bf56220..00000000000000 Binary files a/docs/imgs/apis/tutorials/column-description-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/column-level-lineage-added.png b/docs/imgs/apis/tutorials/column-level-lineage-added.png deleted file mode 100644 index 6092436e0a6a83..00000000000000 Binary files a/docs/imgs/apis/tutorials/column-level-lineage-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/custom-properties-added.png b/docs/imgs/apis/tutorials/custom-properties-added.png deleted file mode 100644 index a7e85d875045c9..00000000000000 Binary files a/docs/imgs/apis/tutorials/custom-properties-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/datahub-main-ui.png b/docs/imgs/apis/tutorials/datahub-main-ui.png deleted file mode 100644 index b058e2683a8513..00000000000000 Binary files a/docs/imgs/apis/tutorials/datahub-main-ui.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/dataset-created.png b/docs/imgs/apis/tutorials/dataset-created.png deleted file mode 100644 index 086dd8b7c9b16e..00000000000000 Binary files a/docs/imgs/apis/tutorials/dataset-created.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/dataset-deleted.png b/docs/imgs/apis/tutorials/dataset-deleted.png deleted file mode 100644 index d94ad7e85195fa..00000000000000 Binary files a/docs/imgs/apis/tutorials/dataset-deleted.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/dataset-description-added.png b/docs/imgs/apis/tutorials/dataset-description-added.png deleted file mode 100644 index 41aa9f109115b2..00000000000000 Binary files a/docs/imgs/apis/tutorials/dataset-description-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/dataset-properties-added-removed.png b/docs/imgs/apis/tutorials/dataset-properties-added-removed.png deleted file mode 100644 index 9eb0284776f13c..00000000000000 Binary files a/docs/imgs/apis/tutorials/dataset-properties-added-removed.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/dataset-properties-added.png b/docs/imgs/apis/tutorials/dataset-properties-added.png deleted file mode 100644 index e0d2acbb66eb5e..00000000000000 Binary files a/docs/imgs/apis/tutorials/dataset-properties-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/dataset-properties-before.png b/docs/imgs/apis/tutorials/dataset-properties-before.png deleted file mode 100644 index b4915121a8c650..00000000000000 Binary files a/docs/imgs/apis/tutorials/dataset-properties-before.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/dataset-properties-replaced.png b/docs/imgs/apis/tutorials/dataset-properties-replaced.png deleted file mode 100644 index 8624689c20ada4..00000000000000 Binary files a/docs/imgs/apis/tutorials/dataset-properties-replaced.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/deprecation-updated.png b/docs/imgs/apis/tutorials/deprecation-updated.png deleted file mode 100644 index 06fedf746f694d..00000000000000 Binary files a/docs/imgs/apis/tutorials/deprecation-updated.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/domain-added.png b/docs/imgs/apis/tutorials/domain-added.png deleted file mode 100644 index cb2002ec9ab4df..00000000000000 Binary files a/docs/imgs/apis/tutorials/domain-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/domain-created.png b/docs/imgs/apis/tutorials/domain-created.png deleted file mode 100644 index cafab2a5e8d5cb..00000000000000 Binary files a/docs/imgs/apis/tutorials/domain-created.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/domain-removed.png b/docs/imgs/apis/tutorials/domain-removed.png deleted file mode 100644 index 1b21172be11d23..00000000000000 Binary files a/docs/imgs/apis/tutorials/domain-removed.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/feature-added-to-model.png b/docs/imgs/apis/tutorials/feature-added-to-model.png deleted file mode 100644 index 311506e4b27839..00000000000000 Binary files a/docs/imgs/apis/tutorials/feature-added-to-model.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/feature-table-created.png b/docs/imgs/apis/tutorials/feature-table-created.png deleted file mode 100644 index 0541cbe572435f..00000000000000 Binary files a/docs/imgs/apis/tutorials/feature-table-created.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/group-upserted.png b/docs/imgs/apis/tutorials/group-upserted.png deleted file mode 100644 index 5283f6273f02a6..00000000000000 Binary files a/docs/imgs/apis/tutorials/group-upserted.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/lineage-added.png b/docs/imgs/apis/tutorials/lineage-added.png deleted file mode 100644 index b381498bad5ac4..00000000000000 Binary files a/docs/imgs/apis/tutorials/lineage-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/model-group-added-to-model.png b/docs/imgs/apis/tutorials/model-group-added-to-model.png deleted file mode 100644 index 360b7fbb2d9220..00000000000000 Binary files a/docs/imgs/apis/tutorials/model-group-added-to-model.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/model-group-created.png b/docs/imgs/apis/tutorials/model-group-created.png deleted file mode 100644 index 2e0fdcea4803f8..00000000000000 Binary files a/docs/imgs/apis/tutorials/model-group-created.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/owner-added.png b/docs/imgs/apis/tutorials/owner-added.png deleted file mode 100644 index 6508c231cfb4ba..00000000000000 Binary files a/docs/imgs/apis/tutorials/owner-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/owner-removed.png b/docs/imgs/apis/tutorials/owner-removed.png deleted file mode 100644 index a7b6567888caf0..00000000000000 Binary files a/docs/imgs/apis/tutorials/owner-removed.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/sample-ingestion.png b/docs/imgs/apis/tutorials/sample-ingestion.png deleted file mode 100644 index 40aa0469048417..00000000000000 Binary files a/docs/imgs/apis/tutorials/sample-ingestion.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/tag-added.png b/docs/imgs/apis/tutorials/tag-added.png deleted file mode 100644 index fd99a04f6cceba..00000000000000 Binary files a/docs/imgs/apis/tutorials/tag-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/tag-created.png b/docs/imgs/apis/tutorials/tag-created.png deleted file mode 100644 index 99e3fea8a14e16..00000000000000 Binary files a/docs/imgs/apis/tutorials/tag-created.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/tag-removed.png b/docs/imgs/apis/tutorials/tag-removed.png deleted file mode 100644 index 31a267549843e5..00000000000000 Binary files a/docs/imgs/apis/tutorials/tag-removed.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/term-added.png b/docs/imgs/apis/tutorials/term-added.png deleted file mode 100644 index 62e285a92e7af0..00000000000000 Binary files a/docs/imgs/apis/tutorials/term-added.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/term-created.png b/docs/imgs/apis/tutorials/term-created.png deleted file mode 100644 index deff0179b155ee..00000000000000 Binary files a/docs/imgs/apis/tutorials/term-created.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/term-removed.png b/docs/imgs/apis/tutorials/term-removed.png deleted file mode 100644 index dbf9f35f093399..00000000000000 Binary files a/docs/imgs/apis/tutorials/term-removed.png and /dev/null differ diff --git a/docs/imgs/apis/tutorials/user-upserted.png b/docs/imgs/apis/tutorials/user-upserted.png deleted file mode 100644 index 38c5bbb9ad8280..00000000000000 Binary files a/docs/imgs/apis/tutorials/user-upserted.png and /dev/null differ diff --git a/docs/imgs/aws/aws-elasticsearch.png b/docs/imgs/aws/aws-elasticsearch.png deleted file mode 100644 index e16d5eee26fd85..00000000000000 Binary files a/docs/imgs/aws/aws-elasticsearch.png and /dev/null differ diff --git a/docs/imgs/aws/aws-msk.png b/docs/imgs/aws/aws-msk.png deleted file mode 100644 index 96a3173747007e..00000000000000 Binary files a/docs/imgs/aws/aws-msk.png and /dev/null differ diff --git a/docs/imgs/aws/aws-rds.png b/docs/imgs/aws/aws-rds.png deleted file mode 100644 index ab329952c77560..00000000000000 Binary files a/docs/imgs/aws/aws-rds.png and /dev/null differ diff --git a/docs/imgs/browse-domains.png b/docs/imgs/browse-domains.png deleted file mode 100644 index 41444470517d2a..00000000000000 Binary files a/docs/imgs/browse-domains.png and /dev/null differ diff --git a/docs/imgs/cancelled-ingestion.png b/docs/imgs/cancelled-ingestion.png deleted file mode 100644 index 0c4af7b66a8ff2..00000000000000 Binary files a/docs/imgs/cancelled-ingestion.png and /dev/null differ diff --git a/docs/imgs/confluent-cloud-config-2.png b/docs/imgs/confluent-cloud-config-2.png deleted file mode 100644 index 543101154f42cf..00000000000000 Binary files a/docs/imgs/confluent-cloud-config-2.png and /dev/null differ diff --git a/docs/imgs/confluent-cloud-config.png b/docs/imgs/confluent-cloud-config.png deleted file mode 100644 index a2490eab5c6a77..00000000000000 Binary files a/docs/imgs/confluent-cloud-config.png and /dev/null differ diff --git a/docs/imgs/confluent-create-topic.png b/docs/imgs/confluent-create-topic.png deleted file mode 100644 index 1972bb3770388f..00000000000000 Binary files a/docs/imgs/confluent-create-topic.png and /dev/null differ diff --git a/docs/imgs/create-domain.png b/docs/imgs/create-domain.png deleted file mode 100644 index 1db2090fca6b89..00000000000000 Binary files a/docs/imgs/create-domain.png and /dev/null differ diff --git a/docs/imgs/create-new-ingestion-source-button.png b/docs/imgs/create-new-ingestion-source-button.png deleted file mode 100644 index c425f0837c51d3..00000000000000 Binary files a/docs/imgs/create-new-ingestion-source-button.png and /dev/null differ diff --git a/docs/imgs/create-secret.png b/docs/imgs/create-secret.png deleted file mode 100644 index a0cc63e3b4892f..00000000000000 Binary files a/docs/imgs/create-secret.png and /dev/null differ diff --git a/docs/imgs/custom-ingestion-cli-version.png b/docs/imgs/custom-ingestion-cli-version.png deleted file mode 100644 index 43d4736684abb1..00000000000000 Binary files a/docs/imgs/custom-ingestion-cli-version.png and /dev/null differ diff --git a/docs/imgs/datahub-architecture.png b/docs/imgs/datahub-architecture.png deleted file mode 100644 index 236f939f74198b..00000000000000 Binary files a/docs/imgs/datahub-architecture.png and /dev/null differ diff --git a/docs/imgs/datahub-architecture.svg b/docs/imgs/datahub-architecture.svg deleted file mode 100644 index 842194a5e377ce..00000000000000 --- a/docs/imgs/datahub-architecture.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/imgs/datahub-components.png b/docs/imgs/datahub-components.png deleted file mode 100644 index 8b7d0e5330275a..00000000000000 Binary files a/docs/imgs/datahub-components.png and /dev/null differ diff --git a/docs/imgs/datahub-logo-color-mark.svg b/docs/imgs/datahub-logo-color-mark.svg deleted file mode 100644 index a984092952bae2..00000000000000 --- a/docs/imgs/datahub-logo-color-mark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/imgs/datahub-metadata-ingestion-framework.png b/docs/imgs/datahub-metadata-ingestion-framework.png deleted file mode 100644 index 1319329710906d..00000000000000 Binary files a/docs/imgs/datahub-metadata-ingestion-framework.png and /dev/null differ diff --git a/docs/imgs/datahub-metadata-model.png b/docs/imgs/datahub-metadata-model.png deleted file mode 100644 index 59449cd0d4ef59..00000000000000 Binary files a/docs/imgs/datahub-metadata-model.png and /dev/null differ diff --git a/docs/imgs/datahub-sequence-diagram.png b/docs/imgs/datahub-sequence-diagram.png deleted file mode 100644 index b5a8f8a9c25ce2..00000000000000 Binary files a/docs/imgs/datahub-sequence-diagram.png and /dev/null differ diff --git a/docs/imgs/datahub-serving.png b/docs/imgs/datahub-serving.png deleted file mode 100644 index 67a2f8eb3f0856..00000000000000 Binary files a/docs/imgs/datahub-serving.png and /dev/null differ diff --git a/docs/imgs/development/intellij-remote-debug.png b/docs/imgs/development/intellij-remote-debug.png deleted file mode 100644 index 32a41a75d1dc38..00000000000000 Binary files a/docs/imgs/development/intellij-remote-debug.png and /dev/null differ diff --git a/docs/imgs/domain-entities.png b/docs/imgs/domain-entities.png deleted file mode 100644 index 5766d051fa209f..00000000000000 Binary files a/docs/imgs/domain-entities.png and /dev/null differ diff --git a/docs/imgs/domains-tab.png b/docs/imgs/domains-tab.png deleted file mode 100644 index 20be5b103fdcaa..00000000000000 Binary files a/docs/imgs/domains-tab.png and /dev/null differ diff --git a/docs/imgs/entity-registry-diagram.png b/docs/imgs/entity-registry-diagram.png deleted file mode 100644 index 08cb5edd8e13f2..00000000000000 Binary files a/docs/imgs/entity-registry-diagram.png and /dev/null differ diff --git a/docs/imgs/entity.png b/docs/imgs/entity.png deleted file mode 100644 index cfe9eb38b2921e..00000000000000 Binary files a/docs/imgs/entity.png and /dev/null differ diff --git a/docs/imgs/example-mysql-recipe.png b/docs/imgs/example-mysql-recipe.png deleted file mode 100644 index 9cb2cbb169a569..00000000000000 Binary files a/docs/imgs/example-mysql-recipe.png and /dev/null differ diff --git a/docs/imgs/failed-ingestion.png b/docs/imgs/failed-ingestion.png deleted file mode 100644 index 4f9de8eb002d2f..00000000000000 Binary files a/docs/imgs/failed-ingestion.png and /dev/null differ diff --git a/docs/imgs/feature-create-new-tag.gif b/docs/imgs/feature-create-new-tag.gif deleted file mode 100644 index 57b8ad852dd5b2..00000000000000 Binary files a/docs/imgs/feature-create-new-tag.gif and /dev/null differ diff --git a/docs/imgs/feature-datahub-analytics.png b/docs/imgs/feature-datahub-analytics.png deleted file mode 100644 index 7fe66b84682f9a..00000000000000 Binary files a/docs/imgs/feature-datahub-analytics.png and /dev/null differ diff --git a/docs/imgs/feature-rich-documentation.gif b/docs/imgs/feature-rich-documentation.gif deleted file mode 100644 index 48ad7956700226..00000000000000 Binary files a/docs/imgs/feature-rich-documentation.gif and /dev/null differ diff --git a/docs/imgs/feature-tag-browse.gif b/docs/imgs/feature-tag-browse.gif deleted file mode 100644 index e70a30db7d3ba9..00000000000000 Binary files a/docs/imgs/feature-tag-browse.gif and /dev/null differ diff --git a/docs/imgs/feature-validation-timeseries.png b/docs/imgs/feature-validation-timeseries.png deleted file mode 100644 index 28ce1daec5f32e..00000000000000 Binary files a/docs/imgs/feature-validation-timeseries.png and /dev/null differ diff --git a/docs/imgs/feature-view-entitiy-details-via-lineage-vis.gif b/docs/imgs/feature-view-entitiy-details-via-lineage-vis.gif deleted file mode 100644 index aad77df3735747..00000000000000 Binary files a/docs/imgs/feature-view-entitiy-details-via-lineage-vis.gif and /dev/null differ diff --git a/docs/imgs/gcp/ingress1.png b/docs/imgs/gcp/ingress1.png deleted file mode 100644 index 4cb49834af5b60..00000000000000 Binary files a/docs/imgs/gcp/ingress1.png and /dev/null differ diff --git a/docs/imgs/gcp/ingress2.png b/docs/imgs/gcp/ingress2.png deleted file mode 100644 index cdf2446b0e923b..00000000000000 Binary files a/docs/imgs/gcp/ingress2.png and /dev/null differ diff --git a/docs/imgs/gcp/ingress3.png b/docs/imgs/gcp/ingress3.png deleted file mode 100644 index cc3745ad97f5bd..00000000000000 Binary files a/docs/imgs/gcp/ingress3.png and /dev/null differ diff --git a/docs/imgs/gcp/ingress_final.png b/docs/imgs/gcp/ingress_final.png deleted file mode 100644 index a30ca744c49f76..00000000000000 Binary files a/docs/imgs/gcp/ingress_final.png and /dev/null differ diff --git a/docs/imgs/gcp/ingress_ready.png b/docs/imgs/gcp/ingress_ready.png deleted file mode 100644 index d14016e420fd3d..00000000000000 Binary files a/docs/imgs/gcp/ingress_ready.png and /dev/null differ diff --git a/docs/imgs/gcp/services_ingress.png b/docs/imgs/gcp/services_ingress.png deleted file mode 100644 index 1d9ff2b313715c..00000000000000 Binary files a/docs/imgs/gcp/services_ingress.png and /dev/null differ diff --git a/docs/imgs/glossary/add-term-modal.png b/docs/imgs/glossary/add-term-modal.png deleted file mode 100644 index e32a9cb8d648c6..00000000000000 Binary files a/docs/imgs/glossary/add-term-modal.png and /dev/null differ diff --git a/docs/imgs/glossary/add-term-to-entity.png b/docs/imgs/glossary/add-term-to-entity.png deleted file mode 100644 index 7487a68c0d7559..00000000000000 Binary files a/docs/imgs/glossary/add-term-to-entity.png and /dev/null differ diff --git a/docs/imgs/glossary/create-from-node.png b/docs/imgs/glossary/create-from-node.png deleted file mode 100644 index 70638d083343c2..00000000000000 Binary files a/docs/imgs/glossary/create-from-node.png and /dev/null differ diff --git a/docs/imgs/glossary/create-modal.png b/docs/imgs/glossary/create-modal.png deleted file mode 100644 index e84fb5a36e2d40..00000000000000 Binary files a/docs/imgs/glossary/create-modal.png and /dev/null differ diff --git a/docs/imgs/glossary/delete-button.png b/docs/imgs/glossary/delete-button.png deleted file mode 100644 index 3e0cc2a5b0a54a..00000000000000 Binary files a/docs/imgs/glossary/delete-button.png and /dev/null differ diff --git a/docs/imgs/glossary/edit-term.png b/docs/imgs/glossary/edit-term.png deleted file mode 100644 index 62b0e425c8c4f3..00000000000000 Binary files a/docs/imgs/glossary/edit-term.png and /dev/null differ diff --git a/docs/imgs/glossary/glossary-button.png b/docs/imgs/glossary/glossary-button.png deleted file mode 100644 index e4b8fd23935877..00000000000000 Binary files a/docs/imgs/glossary/glossary-button.png and /dev/null differ diff --git a/docs/imgs/glossary/move-term-button.png b/docs/imgs/glossary/move-term-button.png deleted file mode 100644 index df03c820340eff..00000000000000 Binary files a/docs/imgs/glossary/move-term-button.png and /dev/null differ diff --git a/docs/imgs/glossary/move-term-modal.png b/docs/imgs/glossary/move-term-modal.png deleted file mode 100644 index 0fda501911b2b0..00000000000000 Binary files a/docs/imgs/glossary/move-term-modal.png and /dev/null differ diff --git a/docs/imgs/glossary/root-glossary-create.png b/docs/imgs/glossary/root-glossary-create.png deleted file mode 100644 index c91f397eb6213c..00000000000000 Binary files a/docs/imgs/glossary/root-glossary-create.png and /dev/null differ diff --git a/docs/imgs/glossary/root-glossary.png b/docs/imgs/glossary/root-glossary.png deleted file mode 100644 index 1296c16b0dc3d1..00000000000000 Binary files a/docs/imgs/glossary/root-glossary.png and /dev/null differ diff --git a/docs/imgs/ingestion-architecture.png b/docs/imgs/ingestion-architecture.png deleted file mode 100644 index fc7bc74acacfaf..00000000000000 Binary files a/docs/imgs/ingestion-architecture.png and /dev/null differ diff --git a/docs/imgs/ingestion-logs.png b/docs/imgs/ingestion-logs.png deleted file mode 100644 index 42211be7379d6e..00000000000000 Binary files a/docs/imgs/ingestion-logs.png and /dev/null differ diff --git a/docs/imgs/ingestion-privileges.png b/docs/imgs/ingestion-privileges.png deleted file mode 100644 index 8e23868309676c..00000000000000 Binary files a/docs/imgs/ingestion-privileges.png and /dev/null differ diff --git a/docs/imgs/ingestion-tab.png b/docs/imgs/ingestion-tab.png deleted file mode 100644 index 046068c63bdb7b..00000000000000 Binary files a/docs/imgs/ingestion-tab.png and /dev/null differ diff --git a/docs/imgs/ingestion-with-token.png b/docs/imgs/ingestion-with-token.png deleted file mode 100644 index 5e1a2cce036f7a..00000000000000 Binary files a/docs/imgs/ingestion-with-token.png and /dev/null differ diff --git a/docs/imgs/invite-users-button.png b/docs/imgs/invite-users-button.png deleted file mode 100644 index a5d07a1c1e7e75..00000000000000 Binary files a/docs/imgs/invite-users-button.png and /dev/null differ diff --git a/docs/imgs/invite-users-popup.png b/docs/imgs/invite-users-popup.png deleted file mode 100644 index 621b1521eae752..00000000000000 Binary files a/docs/imgs/invite-users-popup.png and /dev/null differ diff --git a/docs/imgs/lineage.png b/docs/imgs/lineage.png deleted file mode 100644 index 7488c1e04c31b2..00000000000000 Binary files a/docs/imgs/lineage.png and /dev/null differ diff --git a/docs/imgs/list-domains.png b/docs/imgs/list-domains.png deleted file mode 100644 index 98a28130f8c990..00000000000000 Binary files a/docs/imgs/list-domains.png and /dev/null differ diff --git a/docs/imgs/locust-example.png b/docs/imgs/locust-example.png deleted file mode 100644 index bbae3e0ca19d07..00000000000000 Binary files a/docs/imgs/locust-example.png and /dev/null differ diff --git a/docs/imgs/metadata-model-chart.png b/docs/imgs/metadata-model-chart.png deleted file mode 100644 index 2fb74836549063..00000000000000 Binary files a/docs/imgs/metadata-model-chart.png and /dev/null differ diff --git a/docs/imgs/metadata-model-to-fork-or-not-to.png b/docs/imgs/metadata-model-to-fork-or-not-to.png deleted file mode 100644 index f9d89d555196d1..00000000000000 Binary files a/docs/imgs/metadata-model-to-fork-or-not-to.png and /dev/null differ diff --git a/docs/imgs/metadata-modeling.png b/docs/imgs/metadata-modeling.png deleted file mode 100644 index cbad7613e04e43..00000000000000 Binary files a/docs/imgs/metadata-modeling.png and /dev/null differ diff --git a/docs/imgs/metadata-service-auth.png b/docs/imgs/metadata-service-auth.png deleted file mode 100644 index 15a3ac51876c23..00000000000000 Binary files a/docs/imgs/metadata-service-auth.png and /dev/null differ diff --git a/docs/imgs/metadata-serving.png b/docs/imgs/metadata-serving.png deleted file mode 100644 index 54b928a0cff52e..00000000000000 Binary files a/docs/imgs/metadata-serving.png and /dev/null differ diff --git a/docs/imgs/metadata.png b/docs/imgs/metadata.png deleted file mode 100644 index 45bb0cdce12e95..00000000000000 Binary files a/docs/imgs/metadata.png and /dev/null differ diff --git a/docs/imgs/name-ingestion-source.png b/docs/imgs/name-ingestion-source.png deleted file mode 100644 index bde12082484738..00000000000000 Binary files a/docs/imgs/name-ingestion-source.png and /dev/null differ diff --git a/docs/imgs/no-code-after.png b/docs/imgs/no-code-after.png deleted file mode 100644 index c0eee88625ace9..00000000000000 Binary files a/docs/imgs/no-code-after.png and /dev/null differ diff --git a/docs/imgs/no-code-before.png b/docs/imgs/no-code-before.png deleted file mode 100644 index 50315578b1804a..00000000000000 Binary files a/docs/imgs/no-code-before.png and /dev/null differ diff --git a/docs/imgs/platform-instances-for-ingestion.png b/docs/imgs/platform-instances-for-ingestion.png deleted file mode 100644 index 740249a805fb85..00000000000000 Binary files a/docs/imgs/platform-instances-for-ingestion.png and /dev/null differ diff --git a/docs/imgs/quickstart-ingestion-config.png b/docs/imgs/quickstart-ingestion-config.png deleted file mode 100644 index de51777ccddc3a..00000000000000 Binary files a/docs/imgs/quickstart-ingestion-config.png and /dev/null differ diff --git a/docs/imgs/reset-credentials-screen.png b/docs/imgs/reset-credentials-screen.png deleted file mode 100644 index 4b680837b77ab1..00000000000000 Binary files a/docs/imgs/reset-credentials-screen.png and /dev/null differ diff --git a/docs/imgs/reset-user-password-button.png b/docs/imgs/reset-user-password-button.png deleted file mode 100644 index 5b1f3ee153d072..00000000000000 Binary files a/docs/imgs/reset-user-password-button.png and /dev/null differ diff --git a/docs/imgs/reset-user-password-popup.png b/docs/imgs/reset-user-password-popup.png deleted file mode 100644 index ac2456dde4d4d3..00000000000000 Binary files a/docs/imgs/reset-user-password-popup.png and /dev/null differ diff --git a/docs/imgs/running-ingestion.png b/docs/imgs/running-ingestion.png deleted file mode 100644 index a03fb444a029ed..00000000000000 Binary files a/docs/imgs/running-ingestion.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/10_outputs.png b/docs/imgs/s3-ingestion/10_outputs.png deleted file mode 100644 index e0d1ed3376ade9..00000000000000 Binary files a/docs/imgs/s3-ingestion/10_outputs.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/1_crawler-info.png b/docs/imgs/s3-ingestion/1_crawler-info.png deleted file mode 100644 index 12882473920479..00000000000000 Binary files a/docs/imgs/s3-ingestion/1_crawler-info.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/2_crawler-type.png b/docs/imgs/s3-ingestion/2_crawler-type.png deleted file mode 100644 index 4898438417913c..00000000000000 Binary files a/docs/imgs/s3-ingestion/2_crawler-type.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/3_data-store.png b/docs/imgs/s3-ingestion/3_data-store.png deleted file mode 100644 index d29e4b1be05d65..00000000000000 Binary files a/docs/imgs/s3-ingestion/3_data-store.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/4_data-store-2.png b/docs/imgs/s3-ingestion/4_data-store-2.png deleted file mode 100644 index c0a6f140bedb22..00000000000000 Binary files a/docs/imgs/s3-ingestion/4_data-store-2.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/5_iam.png b/docs/imgs/s3-ingestion/5_iam.png deleted file mode 100644 index 73a631cb74f560..00000000000000 Binary files a/docs/imgs/s3-ingestion/5_iam.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/6_schedule.png b/docs/imgs/s3-ingestion/6_schedule.png deleted file mode 100644 index c5df59348fbc69..00000000000000 Binary files a/docs/imgs/s3-ingestion/6_schedule.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/7_output.png b/docs/imgs/s3-ingestion/7_output.png deleted file mode 100644 index 6201fa40bcfb33..00000000000000 Binary files a/docs/imgs/s3-ingestion/7_output.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/8_review.png b/docs/imgs/s3-ingestion/8_review.png deleted file mode 100644 index 2d27e79c2128b8..00000000000000 Binary files a/docs/imgs/s3-ingestion/8_review.png and /dev/null differ diff --git a/docs/imgs/s3-ingestion/9_run.png b/docs/imgs/s3-ingestion/9_run.png deleted file mode 100644 index 2b0644f6ad0384..00000000000000 Binary files a/docs/imgs/s3-ingestion/9_run.png and /dev/null differ diff --git a/docs/imgs/schedule-ingestion.png b/docs/imgs/schedule-ingestion.png deleted file mode 100644 index 0e6ec8e268c32a..00000000000000 Binary files a/docs/imgs/schedule-ingestion.png and /dev/null differ diff --git a/docs/imgs/schema-blame-blame-activated.png b/docs/imgs/schema-blame-blame-activated.png deleted file mode 100644 index 363466c39aedfb..00000000000000 Binary files a/docs/imgs/schema-blame-blame-activated.png and /dev/null differ diff --git a/docs/imgs/schema-history-audit-activated.png b/docs/imgs/schema-history-audit-activated.png deleted file mode 100644 index f59676b9b8a8fd..00000000000000 Binary files a/docs/imgs/schema-history-audit-activated.png and /dev/null differ diff --git a/docs/imgs/schema-history-latest-version.png b/docs/imgs/schema-history-latest-version.png deleted file mode 100644 index 0a54df4d520d53..00000000000000 Binary files a/docs/imgs/schema-history-latest-version.png and /dev/null differ diff --git a/docs/imgs/schema-history-older-version.png b/docs/imgs/schema-history-older-version.png deleted file mode 100644 index 8d295f176104f7..00000000000000 Binary files a/docs/imgs/schema-history-older-version.png and /dev/null differ diff --git a/docs/imgs/search-by-domain.png b/docs/imgs/search-by-domain.png deleted file mode 100644 index 4b92e589591877..00000000000000 Binary files a/docs/imgs/search-by-domain.png and /dev/null differ diff --git a/docs/imgs/search-domain.png b/docs/imgs/search-domain.png deleted file mode 100644 index b1359e07d5fc21..00000000000000 Binary files a/docs/imgs/search-domain.png and /dev/null differ diff --git a/docs/imgs/search-tag.png b/docs/imgs/search-tag.png deleted file mode 100644 index cf4b6b629d1e23..00000000000000 Binary files a/docs/imgs/search-tag.png and /dev/null differ diff --git a/docs/imgs/select-platform-template.png b/docs/imgs/select-platform-template.png deleted file mode 100644 index 4f78e2b7309edc..00000000000000 Binary files a/docs/imgs/select-platform-template.png and /dev/null differ diff --git a/docs/imgs/set-domain-id.png b/docs/imgs/set-domain-id.png deleted file mode 100644 index 3e1dde4ae51ee1..00000000000000 Binary files a/docs/imgs/set-domain-id.png and /dev/null differ diff --git a/docs/imgs/set-domain.png b/docs/imgs/set-domain.png deleted file mode 100644 index 1c4460e747835d..00000000000000 Binary files a/docs/imgs/set-domain.png and /dev/null differ diff --git a/docs/imgs/successful-ingestion.png b/docs/imgs/successful-ingestion.png deleted file mode 100644 index fa8dbdff7501ed..00000000000000 Binary files a/docs/imgs/successful-ingestion.png and /dev/null differ diff --git a/docs/imgs/timeline/dropdown-apis.png b/docs/imgs/timeline/dropdown-apis.png deleted file mode 100644 index f7aba08bbc061f..00000000000000 Binary files a/docs/imgs/timeline/dropdown-apis.png and /dev/null differ diff --git a/docs/imgs/timeline/swagger-ui.png b/docs/imgs/timeline/swagger-ui.png deleted file mode 100644 index e52a57e8ca6706..00000000000000 Binary files a/docs/imgs/timeline/swagger-ui.png and /dev/null differ diff --git a/docs/imgs/timeline/timeline-conceptually.png b/docs/imgs/timeline/timeline-conceptually.png deleted file mode 100644 index 70bd843bf8aed7..00000000000000 Binary files a/docs/imgs/timeline/timeline-conceptually.png and /dev/null differ diff --git a/docs/imgs/user-sign-up-screen.png b/docs/imgs/user-sign-up-screen.png deleted file mode 100644 index 88c2589203bd18..00000000000000 Binary files a/docs/imgs/user-sign-up-screen.png and /dev/null differ diff --git a/docs/lineage/airflow.md b/docs/lineage/airflow.md index 21d59b777dd7c6..49de5352f6d58c 100644 --- a/docs/lineage/airflow.md +++ b/docs/lineage/airflow.md @@ -65,7 +65,7 @@ lazy_load_plugins = False | datahub.capture_executions | true | If true, we'll capture task runs in DataHub in addition to DAG definitions. | | datahub.graceful_exceptions | true | If set to true, most runtime errors in the lineage backend will be suppressed and will not cause the overall task to fail. Note that configuration issues will still throw exceptions. | -5. Configure `inlets` and `outlets` for your Airflow operators. For reference, look at the sample DAG in [`lineage_backend_demo.py`](../../metadata-ingestion/src/datahub_provider/example_dags/lineage_backend_demo.py), or reference [`lineage_backend_taskflow_demo.py`](../../metadata-ingestion/src/datahub_provider/example_dags/lineage_backend_taskflow_demo.py) if you're using the [TaskFlow API](https://airflow.apache.org/docs/apache-airflow/stable/concepts/taskflow.html). +5. Configure `inlets` and `outlets` for your Airflow operators. For reference, look at the sample DAG in [`lineage_backend_demo.py`](../../metadata-ingestion-modules/airflow-plugin/src/datahub_airflow_plugin/example_dags/lineage_backend_demo.py), or reference [`lineage_backend_taskflow_demo.py`](../../metadata-ingestion-modules/airflow-plugin/src/datahub_airflow_plugin/example_dags/lineage_backend_taskflow_demo.py) if you're using the [TaskFlow API](https://airflow.apache.org/docs/apache-airflow/stable/concepts/taskflow.html). 6. [optional] Learn more about [Airflow lineage](https://airflow.apache.org/docs/apache-airflow/stable/lineage.html), including shorthand notation and some automation. ### How to validate installation @@ -160,14 +160,14 @@ pip install acryl-datahub[airflow,datahub-kafka] - `capture_executions` (defaults to false): If true, it captures task runs as DataHub DataProcessInstances. - `graceful_exceptions` (defaults to true): If set to true, most runtime errors in the lineage backend will be suppressed and will not cause the overall task to fail. Note that configuration issues will still throw exceptions. -4. Configure `inlets` and `outlets` for your Airflow operators. For reference, look at the sample DAG in [`lineage_backend_demo.py`](../../metadata-ingestion/src/datahub_provider/example_dags/lineage_backend_demo.py), or reference [`lineage_backend_taskflow_demo.py`](../../metadata-ingestion/src/datahub_provider/example_dags/lineage_backend_taskflow_demo.py) if you're using the [TaskFlow API](https://airflow.apache.org/docs/apache-airflow/stable/concepts/taskflow.html). +4. Configure `inlets` and `outlets` for your Airflow operators. For reference, look at the sample DAG in [`lineage_backend_demo.py`](../../metadata-ingestion-modules/airflow-plugin/src/datahub_airflow_plugin/example_dags/lineage_backend_demo.py), or reference [`lineage_backend_taskflow_demo.py`](../../metadata-ingestion-modules/airflow-plugin/src/datahub_airflow_plugin/example_dags/lineage_backend_taskflow_demo.py) if you're using the [TaskFlow API](https://airflow.apache.org/docs/apache-airflow/stable/concepts/taskflow.html). 5. [optional] Learn more about [Airflow lineage](https://airflow.apache.org/docs/apache-airflow/stable/lineage.html), including shorthand notation and some automation. ## Emitting lineage via a separate operator Take a look at this sample DAG: -- [`lineage_emission_dag.py`](../../metadata-ingestion/src/datahub_provider/example_dags/lineage_emission_dag.py) - emits lineage using the DatahubEmitterOperator. +- [`lineage_emission_dag.py`](../../metadata-ingestion-modules/airflow-plugin/src/datahub_airflow_plugin/example_dags/lineage_emission_dag.py) - emits lineage using the DatahubEmitterOperator. In order to use this example, you must first configure the Datahub hook. Like in ingestion, we support a Datahub REST hook and a Kafka-based hook. See step 1 above for details. diff --git a/docs/links.md b/docs/links.md index f175262b9b5d93..45ba391e557cdb 100644 --- a/docs/links.md +++ b/docs/links.md @@ -39,7 +39,7 @@ * [Creating Notebook-based Dynamic Dashboards](https://towardsdatascience.com/creating-notebook-based-dynamic-dashboards-91f936adc6f3) ## Talks & Presentations -* [DataHub: Powering LinkedIn's Metadata](demo/DataHub_-_Powering_LinkedIn_Metadata.pdf) @ [Budapest Data Forum 2020](https://budapestdata.hu/2020/en/) +* [DataHub: Powering LinkedIn's Metadata](https://github.com/acryldata/static-assets-test/raw/master/imgs/demo/DataHub_-_Powering_LinkedIn_Metadata.pdf) @ [Budapest Data Forum 2020](https://budapestdata.hu/2020/en/) * [Taming the Data Beast Using DataHub](https://www.youtube.com/watch?v=bo4OhiPro7Y) @ [Data Engineering Melbourne Meetup November 2020](https://www.meetup.com/Data-Engineering-Melbourne/events/kgnvlrybcpbjc/) * [Metadata Management And Integration At LinkedIn With DataHub](https://www.dataengineeringpodcast.com/datahub-metadata-management-episode-147/) @ [Data Engineering Podcast](https://www.dataengineeringpodcast.com) * [The evolution of metadata: LinkedIn’s story](https://speakerdeck.com/shirshanka/the-evolution-of-metadata-linkedins-journey-strata-nyc-2019) @ [Strata Data Conference 2019](https://conferences.oreilly.com/strata/strata-ny-2019.html) diff --git a/docs/managed-datahub/chrome-extension.md b/docs/managed-datahub/chrome-extension.md index a614327c7fd29d..0aa0860d03b67a 100644 --- a/docs/managed-datahub/chrome-extension.md +++ b/docs/managed-datahub/chrome-extension.md @@ -10,7 +10,11 @@ import FeatureAvailability from '@site/src/components/FeatureAvailability'; In order to use the Acryl DataHub Chrome extension, you need to download it onto your browser from the Chrome web store [here](https://chrome.google.com/webstore/detail/datahub-chrome-extension/aoenebhmfokhglijmoacfjcnebdpchfj). -![](imgs/saas/chrome-store-extension-screenshot.png) + +

+ +

+ Simply click "Add to Chrome" then "Add extension" on the ensuing popup. @@ -20,11 +24,19 @@ Once you have your extension installed, you'll need to configure it to work with 1. Click the extension button on the right of your browser's address bar to view all of your installed extensions. Click on the newly installed DataHub extension. -![](imgs/saas/extension_open_popup.png) + +

+ +

+ 2. Fill in your DataHub domain and click "Continue" in the extension popup that appears. -![](imgs/saas/extension_enter_domain.png) + +

+ +

+ If your organization uses standard SaaS domains for Looker, you should be ready to go! @@ -34,11 +46,19 @@ Some organizations have custom SaaS domains for Looker and some Acryl DataHub de 1. Click on the extension button and select your DataHub extension to open the popup again. Now click the settings icon in order to open the configurations page. -![](imgs/saas/extension_open_options_page.png) + +

+ +

+ 2. Fill out any and save custom configurations you have in the **TOOL CONFIGURATIONS** section. Here you can configure a custom domain, a Platform Instance associated with that domain, and the Environment set on your DataHub assets. If you don't have a custom domain but do have a custom Platform Instance or Environment, feel free to leave the field domain empty. -![](imgs/saas/extension_custom_configs.png) + +

+ +

+ ## Using the Extension @@ -52,7 +72,11 @@ Once you have everything configured on your extension, it's time to use it! 4. Click the Acryl DataHub extension button on the bottom right of your page to open a drawer where you can now see additional information about this asset right from your DataHub instance. -![](imgs/saas/extension_view_in_looker.png) + +

+ +

+ ## Advanced: Self-Hosted DataHub diff --git a/docs/managed-datahub/datahub-api/graphql-api/getting-started.md b/docs/managed-datahub/datahub-api/graphql-api/getting-started.md index 3c57b0a21d96e4..736bf6fea6811d 100644 --- a/docs/managed-datahub/datahub-api/graphql-api/getting-started.md +++ b/docs/managed-datahub/datahub-api/graphql-api/getting-started.md @@ -10,7 +10,11 @@ For a full reference to the Queries & Mutations available for consumption, check ### Connecting to the API -![](../../imgs/saas/image-(3).png) + +

+ +

+ When you generate the token you will see an example of `curl` command which you can use to connect to the GraphQL API. diff --git a/docs/managed-datahub/datahub-api/graphql-api/incidents-api-beta.md b/docs/managed-datahub/datahub-api/graphql-api/incidents-api-beta.md index 89bacb2009e494..16d83d2f575752 100644 --- a/docs/managed-datahub/datahub-api/graphql-api/incidents-api-beta.md +++ b/docs/managed-datahub/datahub-api/graphql-api/incidents-api-beta.md @@ -404,7 +404,11 @@ You can configure Acryl to send slack notifications to a specific channel when i These notifications are also able to tag the immediate asset's owners, along with the owners of downstream assets consuming it. -![](../../imgs/saas/Screen-Shot-2022-03-22-at-6.46.41-PM.png) + +

+ +

+ To do so, simply follow the [Slack Integration Guide](docs/managed-datahub/saas-slack-setup.md) and contact your Acryl customer success team to enable the feature! diff --git a/docs/managed-datahub/imgs/saas/DataHub-Architecture.png b/docs/managed-datahub/imgs/saas/DataHub-Architecture.png deleted file mode 100644 index 95b3ab0b06ad64..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/DataHub-Architecture.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-13-at-7.45.56-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-13-at-7.45.56-PM.png deleted file mode 100644 index 721989a6c37e11..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-13-at-7.45.56-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-24-at-4.35.17-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-24-at-4.35.17-PM.png deleted file mode 100644 index dffac92f257c7b..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-24-at-4.35.17-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-24-at-4.37.22-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-24-at-4.37.22-PM.png deleted file mode 100644 index ff0c29de1fbad3..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-01-24-at-4.37.22-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-07-at-10.23.31-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-07-at-10.23.31-AM.png deleted file mode 100644 index 070bfd9f6b8975..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-07-at-10.23.31-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.43.25-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.43.25-PM.png deleted file mode 100644 index b4bb4e2ba60edc..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.43.25-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.44.15-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.44.15-PM.png deleted file mode 100644 index b0397afd1b3a40..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.44.15-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.46.41-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.46.41-PM.png deleted file mode 100644 index 9258badb6f0889..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-03-22-at-6.46.41-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.52.55-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.52.55-PM.png deleted file mode 100644 index 386b4cdcd99113..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.52.55-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.56.50-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.56.50-PM.png deleted file mode 100644 index a129f5eba4271b..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.56.50-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.58.46-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.58.46-PM.png deleted file mode 100644 index 96ae48318a35a1..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-4.58.46-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-5.01.16-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-5.01.16-PM.png deleted file mode 100644 index b6fd273389c904..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-5.01.16-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-5.03.36-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-5.03.36-PM.png deleted file mode 100644 index 0acd4e75bc6d2c..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-05-at-5.03.36-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-13-at-2.34.24-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-13-at-2.34.24-PM.png deleted file mode 100644 index 364b9292cfaab7..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-04-13-at-2.34.24-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-7.56.16-AM-(1).png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-7.56.16-AM-(1).png deleted file mode 100644 index 6a12dc545ec62c..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-7.56.16-AM-(1).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-7.56.16-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-7.56.16-AM.png deleted file mode 100644 index 6a12dc545ec62c..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-7.56.16-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-8.02.55-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-8.02.55-AM.png deleted file mode 100644 index 83645e00d724a4..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-13-at-8.02.55-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-24-at-11.02.47-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-24-at-11.02.47-AM.png deleted file mode 100644 index a2f239ce847e07..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-24-at-11.02.47-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-24-at-12.59.38-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-24-at-12.59.38-PM.png deleted file mode 100644 index e31d4b089d9292..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-06-24-at-12.59.38-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.21.42-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.21.42-AM.png deleted file mode 100644 index c003581c9d1b63..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.21.42-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.22.23-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.22.23-AM.png deleted file mode 100644 index 660dd121dd0a41..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.22.23-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.23.08-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.23.08-AM.png deleted file mode 100644 index 07e3c71dba262f..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.23.08-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.47.57-AM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.47.57-AM.png deleted file mode 100644 index 579e7f62af7085..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-22-at-11.47.57-AM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-29-at-6.07.25-PM-(1).png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-29-at-6.07.25-PM-(1).png deleted file mode 100644 index f85f4d5c79bfb9..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-29-at-6.07.25-PM-(1).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-29-at-6.07.25-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-29-at-6.07.25-PM.png deleted file mode 100644 index f85f4d5c79bfb9..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2022-08-29-at-6.07.25-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-4.16.52-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-4.16.52-PM.png deleted file mode 100644 index cb8b7470cd957d..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-4.16.52-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-4.23.32-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-4.23.32-PM.png deleted file mode 100644 index 1de51e33d87c23..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-4.23.32-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.47-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.47-PM.png deleted file mode 100644 index df687dabe345c4..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.47-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.56-PM-(1).png b/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.56-PM-(1).png deleted file mode 100644 index a8d9ee37c7a558..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.56-PM-(1).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.56-PM.png b/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.56-PM.png deleted file mode 100644 index a8d9ee37c7a558..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Screen-Shot-2023-01-19-at-5.12.56-PM.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Untitled(1).png b/docs/managed-datahub/imgs/saas/Untitled(1).png deleted file mode 100644 index 87846e7897f6ed..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Untitled(1).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Untitled-(2)-(1).png b/docs/managed-datahub/imgs/saas/Untitled-(2)-(1).png deleted file mode 100644 index 7715bf4a51fbe4..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Untitled-(2)-(1).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Untitled-(2).png b/docs/managed-datahub/imgs/saas/Untitled-(2).png deleted file mode 100644 index a01a1af370442d..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Untitled-(2).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Untitled-(3).png b/docs/managed-datahub/imgs/saas/Untitled-(3).png deleted file mode 100644 index 02d84b326896c8..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Untitled-(3).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Untitled-(4).png b/docs/managed-datahub/imgs/saas/Untitled-(4).png deleted file mode 100644 index a01a1af370442d..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Untitled-(4).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/Untitled.png b/docs/managed-datahub/imgs/saas/Untitled.png deleted file mode 100644 index a01a1af370442d..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/Untitled.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/chrome-store-extension-screenshot.png b/docs/managed-datahub/imgs/saas/chrome-store-extension-screenshot.png deleted file mode 100644 index e00a4d57f32ddc..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/chrome-store-extension-screenshot.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/extension_custom_configs.png b/docs/managed-datahub/imgs/saas/extension_custom_configs.png deleted file mode 100644 index b3d70dfac00ff4..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/extension_custom_configs.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/extension_developer_mode.png b/docs/managed-datahub/imgs/saas/extension_developer_mode.png deleted file mode 100644 index e740d15912e174..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/extension_developer_mode.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/extension_enter_domain.png b/docs/managed-datahub/imgs/saas/extension_enter_domain.png deleted file mode 100644 index 3304fa168beaf1..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/extension_enter_domain.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/extension_load_unpacked.png b/docs/managed-datahub/imgs/saas/extension_load_unpacked.png deleted file mode 100644 index 8f56705cd91769..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/extension_load_unpacked.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/extension_open_options_page.png b/docs/managed-datahub/imgs/saas/extension_open_options_page.png deleted file mode 100644 index c1366d5673b599..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/extension_open_options_page.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/extension_open_popup.png b/docs/managed-datahub/imgs/saas/extension_open_popup.png deleted file mode 100644 index 216056b847fb51..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/extension_open_popup.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/extension_view_in_looker.png b/docs/managed-datahub/imgs/saas/extension_view_in_looker.png deleted file mode 100644 index bf854b3e840f7b..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/extension_view_in_looker.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/home-(1).png b/docs/managed-datahub/imgs/saas/home-(1).png deleted file mode 100644 index 88cf2017dd7e71..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/home-(1).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/home.png b/docs/managed-datahub/imgs/saas/home.png deleted file mode 100644 index 8ad63deec75c9b..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/home.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(1).png b/docs/managed-datahub/imgs/saas/image-(1).png deleted file mode 100644 index c1a249125fcf7c..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(1).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(10).png b/docs/managed-datahub/imgs/saas/image-(10).png deleted file mode 100644 index a580fdc3d67309..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(10).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(11).png b/docs/managed-datahub/imgs/saas/image-(11).png deleted file mode 100644 index ee95eb43842723..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(11).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(12).png b/docs/managed-datahub/imgs/saas/image-(12).png deleted file mode 100644 index bbd8e6a66cf85b..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(12).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(13).png b/docs/managed-datahub/imgs/saas/image-(13).png deleted file mode 100644 index bbd8e6a66cf85b..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(13).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(14).png b/docs/managed-datahub/imgs/saas/image-(14).png deleted file mode 100644 index a580fdc3d67309..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(14).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(15).png b/docs/managed-datahub/imgs/saas/image-(15).png deleted file mode 100644 index f282e2d92c1a1d..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(15).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(16).png b/docs/managed-datahub/imgs/saas/image-(16).png deleted file mode 100644 index 1340c77bd648c8..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(16).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(17).png b/docs/managed-datahub/imgs/saas/image-(17).png deleted file mode 100644 index 6eee2fb2d821fe..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(17).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(2).png b/docs/managed-datahub/imgs/saas/image-(2).png deleted file mode 100644 index cf475edd7b95da..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(2).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(3).png b/docs/managed-datahub/imgs/saas/image-(3).png deleted file mode 100644 index b08818ff3e97c6..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(3).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(4).png b/docs/managed-datahub/imgs/saas/image-(4).png deleted file mode 100644 index a580fdc3d67309..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(4).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(5).png b/docs/managed-datahub/imgs/saas/image-(5).png deleted file mode 100644 index 48438c6001e4f5..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(5).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(6).png b/docs/managed-datahub/imgs/saas/image-(6).png deleted file mode 100644 index 54e569e853f246..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(6).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(7).png b/docs/managed-datahub/imgs/saas/image-(7).png deleted file mode 100644 index 6e89e5881cfa78..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(7).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(8).png b/docs/managed-datahub/imgs/saas/image-(8).png deleted file mode 100644 index ee0a3c89d58faa..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(8).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image-(9).png b/docs/managed-datahub/imgs/saas/image-(9).png deleted file mode 100644 index 301ca98593ef9c..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image-(9).png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/image.png b/docs/managed-datahub/imgs/saas/image.png deleted file mode 100644 index a1cfc3e74c5dd2..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/image.png and /dev/null differ diff --git a/docs/managed-datahub/imgs/saas/settings.png b/docs/managed-datahub/imgs/saas/settings.png deleted file mode 100644 index ca99984abbbc99..00000000000000 Binary files a/docs/managed-datahub/imgs/saas/settings.png and /dev/null differ diff --git a/docs/managed-datahub/integrations/oidc-sso-integration.md b/docs/managed-datahub/integrations/oidc-sso-integration.md index 6a9e085186b446..ec4ca311a0de54 100644 --- a/docs/managed-datahub/integrations/oidc-sso-integration.md +++ b/docs/managed-datahub/integrations/oidc-sso-integration.md @@ -42,4 +42,8 @@ To enable the OIDC integration, start by navigating to **Settings > Platform > S 4. If there are any advanced settings you would like to configure, click on the **Advanced** button. These come with defaults, so only input settings here if there is something you need changed from the default configuration. 5. Click **Update** to save your settings. -![](../imgs/saas/image-(10).png) + +

+ +

+ diff --git a/docs/managed-datahub/metadata-ingestion-with-acryl/ingestion.md b/docs/managed-datahub/metadata-ingestion-with-acryl/ingestion.md index 95ca6e5e33e160..0444d15b3627cb 100644 --- a/docs/managed-datahub/metadata-ingestion-with-acryl/ingestion.md +++ b/docs/managed-datahub/metadata-ingestion-with-acryl/ingestion.md @@ -56,9 +56,17 @@ In Acryl DataHub deployments, you _must_ use a sink of type `datahub-rest`, whic 2. **token**: a unique API key used to authenticate requests to your instance's REST API The token can be retrieved by logging in as admin. You can go to Settings page and generate a Personal Access Token with your desired expiration date. -![](../imgs/saas/home-(1).png) -![](../imgs/saas/settings.png) +

+ +

+ + + +

+ +

+ To configure your instance of DataHub as the destination for ingestion, set the "server" field of your recipe to point to your Acryl instance's domain suffixed by the path `/gms`, as shown below. A complete example of a DataHub recipe file, which reads from MySQL and writes into a DataHub instance: diff --git a/docs/managed-datahub/observe/freshness-assertions.md b/docs/managed-datahub/observe/freshness-assertions.md index 54b3134151d3a2..c5d4ca9081b43d 100644 --- a/docs/managed-datahub/observe/freshness-assertions.md +++ b/docs/managed-datahub/observe/freshness-assertions.md @@ -59,7 +59,7 @@ Tables. For example, imagine that we work for a company with a Snowflake Table that stores user clicks collected from our e-commerce website. This table is updated with new data on a specific cadence: once per hour (In practice, daily or even weekly are also common). In turn, there is a downstream Business Analytics Dashboard in Looker that shows important metrics like -the number of people clicking our "Daily Sale" banners, and this dashboard pulls is generated from data stored in our "clicks" table. +the number of people clicking our "Daily Sale" banners, and this dashboard is generated from data stored in our "clicks" table. It is important that our clicks Table continues to be updated each hour because if it stops being updated, it could mean that our downstream metrics dashboard becomes incorrect. And the risk of this situation is obvious: our organization may make bad decisions based on incomplete information. @@ -122,8 +122,12 @@ Change Source types vary by the platform, but generally fall into these categori is higher than the previously observed value, in order to determine whether the Table has been changed within a given period of time. Note that this approach is only supported if the Change Window does not use a fixed interval. - Using the final 2 approaches - column value queries - to determine whether a Table has changed useful because it can be customized to determine whether - specific types of important changes have been made to a given Table. + - **DataHub Operation**: A DataHub "Operation" aspect contains timeseries information used to describe changes made to an entity. Using this + option avoids contacting your data platform, and instead uses the DataHub Operation metadata to evaluate Freshness Assertions. + This relies on Operations being reported to DataHub, either via ingestion or via use of the DataHub APIs (see [Report Operation via API](#reporting-operations-via-api)). + Note if you have not configured an ingestion source through DataHub, then this may be the only option available. + + Using either of the column value approaches (**Last Modified Column** or **High Watermark Column**) to determine whether a Table has changed can be useful because it can be customized to determine whether specific types of important changes have been made to a given Table. Because it does not involve system warehouse tables, it is also easily portable across Data Warehouse and Data Lake providers. Freshness Assertions also have an off switch: they can be started or stopped at any time with the click of button. @@ -178,7 +182,7 @@ _Check whether the table has changed in a specific window of time_ 7. (Optional) Click **Advanced** to customize the evaluation **source**. This is the mechanism that will be used to evaluate -the check. Each Data Platform supports different options including Audit Log, Information Schema, Last Modified Column, and High Watermark Column. +the check. Each Data Platform supports different options including Audit Log, Information Schema, Last Modified Column, High Watermark Column, and DataHub Operation.

@@ -189,11 +193,12 @@ the check. Each Data Platform supports different options including Audit Log, In - **Last Modified Column**: Check for the presence of rows using a "Last Modified Time" column, which should reflect the time at which a given row was last changed in the table, to determine whether the table changed within the evaluation period. - **High Watermark Column**: Monitor changes to a continuously-increasing "high watermark" column value to determine whether a table - has been changed. This option is particularly useful for tables that grow consistently with time, for example fact or event (e.g. click-strea) tables. It is not available + has been changed. This option is particularly useful for tables that grow consistently with time, for example fact or event (e.g. click-stream) tables. It is not available when using a fixed lookback period. +- **DataHub Operation**: Use DataHub Operations to determine whether the table changed within the evaluation period. -8. Click **Next** -9. Configure actions that should be taken when the Freshness Assertion passes or fails +1. Click **Next** +2. Configure actions that should be taken when the Freshness Assertion passes or fails

@@ -280,7 +285,7 @@ Note that to create or delete Assertions and Monitors for a specific entity on D In order to create a Freshness Assertion that is being monitored on a specific **Evaluation Schedule**, you'll need to use 2 GraphQL mutation queries to create a Freshness Assertion entity and create an Assertion Monitor entity responsible for evaluating it. -Start by creating the Freshness Assertion entity using the `createFreshnessAssertion` query and hang on to the 'urn' field of the Assertion entit y +Start by creating the Freshness Assertion entity using the `createFreshnessAssertion` query and hang on to the 'urn' field of the Assertion entity you get back. Then continue by creating a Monitor entity using the `createAssertionMonitor`. ##### Examples @@ -291,10 +296,10 @@ To create a Freshness Assertion Entity that checks whether a table has been upda mutation createFreshnessAssertion { createFreshnessAssertion( input: { - entityUrn: "" - type: DATASET_CHANGE + entityUrn: "", + type: DATASET_CHANGE, schedule: { - type: FIXED_INTERVAL + type: FIXED_INTERVAL, fixedInterval: { unit: HOUR, multiple: 8 } } } @@ -337,6 +342,28 @@ After creating the monitor, the new assertion will start to be evaluated every 8 You can delete assertions along with their monitors using GraphQL mutations: `deleteAssertion` and `deleteMonitor`. +### Reporting Operations via API + +DataHub Operations can be used to capture changes made to entities. This is useful for cases where the underlying data platform does not provide a mechanism +to capture changes, or where the data platform's mechanism is not reliable. In order to report an operation, you can use the `reportOperation` GraphQL mutation. + + +##### Examples +```json +mutation reportOperation { + reportOperation( + input: { + urn: "", + operationType: INSERT, + sourceType: DATA_PLATFORM, + timestampMillis: 1693252366489 + } + ) +} +``` + +Use the `timestampMillis` field to specify the time at which the operation occurred. If no value is provided, the current time will be used. + ### Tips :::info diff --git a/docs/managed-datahub/observe/volume-assertions.md b/docs/managed-datahub/observe/volume-assertions.md new file mode 100644 index 00000000000000..5f5aff33a5ce21 --- /dev/null +++ b/docs/managed-datahub/observe/volume-assertions.md @@ -0,0 +1,355 @@ +--- +description: This page provides an overview of working with DataHub Volume Assertions +--- +import FeatureAvailability from '@site/src/components/FeatureAvailability'; + + +# Volume Assertions + + + + +> ⚠️ The **Volume Assertions** feature is currently in private beta, part of the **Acryl Observe** module, and may only be available to a +> limited set of design partners. +> +> If you are interested in trying it and providing feedback, please reach out to your Acryl Customer Success +> representative. + +## Introduction + +Can you remember a time when the meaning of Data Warehouse Table that you depended on fundamentally changed, with little or no notice? +If the answer is yes, how did you find out? We'll take a guess - someone looking at an internal reporting dashboard or worse, a user using your your product, sounded an alarm when +a number looked a bit out of the ordinary. Perhaps your table initially tracked purchases made on your company's e-commerce web store, but suddenly began to include purchases made +through your company's new mobile app. + +There are many reasons why an important Table on Snowflake, Redshift, or BigQuery may change in its meaning - application code bugs, new feature rollouts, +changes to key metric definitions, etc. Often times, these changes break important assumptions made about the data used in building key downstream data products +like reporting dashboards or data-driven product features. + +What if you could reduce the time to detect these incidents, so that the people responsible for the data were made aware of data +issues _before_ anyone else? With Acryl DataHub **Volume Assertions**, you can. + +Acryl DataHub allows users to define expectations about the normal volume, or size, of a particular warehouse Table, +and then monitor those expectations over time as the table grows and changes. + +In this article, we'll cover the basics of monitoring Volume Assertions - what they are, how to configure them, and more - so that you and your team can +start building trust in your most important data assets. + +Let's get started! + +## Support + +Volume Assertions are currently supported for: + +1. Snowflake +2. Redshift +3. BigQuery + +Note that an Ingestion Source _must_ be configured with the data platform of your choice in Acryl DataHub's **Ingestion** +tab. + +> Note that Volume Assertions are not yet supported if you are connecting to your warehouse +> using the DataHub CLI or a Remote Ingestion Executor. + +## What is a Volume Assertion? + +A **Volume Assertion** is a configurable Data Quality rule used to monitor a Data Warehouse Table +for unexpected or sudden changes in "volume", or row count. Volume Assertions can be particularly useful when you have frequently-changing +Tables which have a relatively stable pattern of growth or decline. + +For example, imagine that we work for a company with a Snowflake Table that stores user clicks collected from our e-commerce website. +This table is updated with new data on a specific cadence: once per hour (In practice, daily or even weekly are also common). +In turn, there is a downstream Business Analytics Dashboard in Looker that shows important metrics like +the number of people clicking our "Daily Sale" banners, and this dashboard is generated from data stored in our "clicks" table. +It is important that our clicks Table is updated with the correct number of rows each hour, else it could mean +that our downstream metrics dashboard becomes incorrect. The risk of this situation is obvious: our organization +may make bad decisions based on incomplete information. + +In such cases, we can use a **Volume Assertion** that checks whether the Snowflake "clicks" Table is growing in an expected +way, and that there are no sudden increases or sudden decreases in the rows being added or removed from the table. +If too many rows are added or removed within an hour, we can notify key stakeholders and begin to root cause before the problem impacts stakeholders of the data. + +### Anatomy of a Volume Assertion + +At the most basic level, **Volume Assertions** consist of a few important parts: + +1. An **Evaluation Schedule** +2. A **Volume Condition** +2. A **Volume Source** + +In this section, we'll give an overview of each. + +#### 1. Evaluation Schedule + +The **Evaluation Schedule**: This defines how often to check a given warehouse Table for its volume. This should usually +be configured to match the expected change frequency of the Table, although it can also be less frequently depending +on the requirements. You can also specify specific days of the week, hours in the day, or even +minutes in an hour. + + +#### 2. Volume Condition + +The **Volume Condition**: This defines the type of condition that we'd like to monitor, or when the Assertion +should result in failure. + +There are a 2 different categories of conditions: **Total** Volume and **Change** Volume. + +_Total_ volume conditions are those which are defined against the point-in-time total row count for a table. They allow you to specify conditions like: + +1. **Table has too many rows**: The table should always have less than 1000 rows +2. **Table has too few rows**: The table should always have more than 1000 rows +3. **Table row count is outside a range**: The table should always have between 1000 and 2000 rows. + +_Change_ volume conditions are those which are defined against the growth or decline rate of a table, measured between subsequent checks +of the table volume. They allow you to specify conditions like: + +1. **Table growth is too fast**: When the table volume is checked, it should have < 1000 more rows than it had during the previous check. +2. **Table growth is too slow**: When the table volume is checked, it should have > 1000 more rows than it had during the previous check. +3. **Table growth is outside a range**: When the table volume is checked, it should have between 1000 and 2000 more rows than it had during the previous check. + +For change volume conditions, both _absolute_ row count deltas and relative percentage deltas are supported for identifying +table that are following an abnormal pattern of growth. + + +#### 3. Volume Source + +The **Volume Source**: This is the mechanism that Acryl DataHub should use to determine the table volume (row count). The supported +source types vary by the platform, but generally fall into these categories: + +- **Information Schema**: A system Table that is exposed by the Data Warehouse which contains live information about the Databases + and Tables stored inside the Data Warehouse, including their row count. It is usually efficient to check, but can in some cases be slightly delayed to update + once a change has been made to a table. + +- **Query**: A `COUNT(*)` query is used to retrieve the latest row count for a table, with optional SQL filters applied (depending on platform). + This can be less efficient to check depending on the size of the table. This approach is more portable, as it does not involve + system warehouse tables, it is also easily portable across Data Warehouse and Data Lake providers. + +- **DataHub Dataset Profile**: The DataHub Dataset Profile aspect is used to retrieve the latest row count information for a table. + Using this option avoids contacting your data platform, and instead uses the DataHub Dataset Profile metadata to evaluate Volume Assertions. + Note if you have not configured an ingestion source through DataHub, then this may be the only option available. + +Volume Assertions also have an off switch: they can be started or stopped at any time with the click of button. + + +## Creating a Volume Assertion + +### Prerequisites + +1. **Permissions**: To create or delete Volume Assertions for a specific entity on DataHub, you'll need to be granted the + `Edit Assertions` and `Edit Monitors` privileges for the entity. This is granted to Entity owners by default. + +2. **Data Platform Connection**: In order to create a Volume Assertion, you'll need to have an **Ingestion Source** configured to your + Data Platform: Snowflake, BigQuery, or Redshift under the **Integrations** tab. + +Once these are in place, you're ready to create your Volume Assertions! + +### Steps + +1. Navigate to the Table that to monitor for volume +2. Click the **Validations** tab + +

+ +

+ +3. Click **+ Create Assertion** + +

+ +

+ +4. Choose **Volume** + +5. Configure the evaluation **schedule**. This is the frequency at which the assertion will be evaluated to produce a pass or fail result, and the times + when the table volume will be checked. + +6. Configure the evaluation **condition type**. This determines the cases in which the new assertion will fail when it is evaluated. + +

+ +

+ +7. (Optional) Click **Advanced** to customize the volume **source**. This is the mechanism that will be used to obtain the table + row count metric. Each Data Platform supports different options including Information Schema, Query, and DataHub Dataset Profile. + +

+ +

+ +- **Information Schema**: Check the Data Platform system metadata tables to determine the table row count. +- **Query**: Issue a `COUNT(*)` query to the table to determine the row count. +- **DataHub Dataset Profile**: Use the DataHub Dataset Profile metadata to determine the row count. + +8. Click **Next** +9. Configure actions that should be taken when the Volume Assertion passes or fails + +

+ +

+ +- **Raise incident**: Automatically raise a new DataHub `Volume` Incident for the Table whenever the Volume Assertion is failing. This + may indicate that the Table is unfit for consumption. Configure Slack Notifications under **Settings** to be notified when + an incident is created due to an Assertion failure. +- **Resolve incident**: Automatically resolved any incidents that were raised due to failures in this Volume Assertion. Note that + any other incidents will not be impacted. + +10. Click **Save**. + +And that's it! DataHub will now begin to monitor your Volume Assertion for the table. + +To view the time of the next Volume Assertion evaluation, simply click **Volume** and then click on your +new Assertion: + +

+ +

+ +Once your assertion has run, you will begin to see Success or Failure status for the Table + +

+ +

+ + +## Stopping a Volume Assertion + +In order to temporarily stop the evaluation of a Volume Assertion: + +1. Navigate to the **Validations** tab of the Table with the assertion +2. Click **Volume** to open the Volume Assertions list +3. Click the three-dot menu on the right side of the assertion you want to disable +4. Click **Stop** + +

+ +

+ +To resume the Volume Assertion, simply click **Turn On**. + +

+ +

+ + +## Smart Assertions ⚡ + +As part of the **Acryl Observe** module, Acryl DataHub also provides **Smart Assertions** out of the box. These are +dynamic, AI-powered Volume Assertions that you can use to monitor the volume of important warehouse Tables, without +requiring any manual setup. + +If Acryl DataHub is able to detect a pattern in the volume of a Snowflake, Redshift, or BigQuery Table, you'll find +a recommended Smart Assertion under the `Validations` tab on the Table profile page: + +

+ +

+ +In order to enable it, simply click **Turn On**. From this point forward, the Smart Assertion will check for changes on a cadence +based on the Table history. + +Don't need it anymore? Smart Assertions can just as easily be turned off by clicking the three-dot "more" button and then **Stop**. + + +## Creating Volume Assertions via API + +Under the hood, Acryl DataHub implements Volume Assertion Monitoring using two "entity" concepts: + +- **Assertion**: The specific expectation for volume, e.g. "The table was changed int the past 7 hours" + or "The table is changed on a schedule of every day by 8am". This is the "what". + +- **Monitor**: The process responsible for evaluating the Assertion on a given evaluation schedule and using specific + mechanisms. This is the "how". + +Note that to create or delete Assertions and Monitors for a specific entity on DataHub, you'll need the +`Edit Assertions` and `Edit Monitors` privileges for it. + +#### GraphQL + +In order to create a Volume Assertion that is being monitored on a specific **Evaluation Schedule**, you'll need to use 2 +GraphQL mutation queries to create a Volume Assertion entity and create an Assertion Monitor entity responsible for evaluating it. + +Start by creating the Volume Assertion entity using the `createVolumeAssertion` query and hang on to the 'urn' field of the Assertion entity +you get back. Then continue by creating a Monitor entity using the `createAssertionMonitor`. + +##### Examples + +To create a Volume Assertion Entity that checks whether a table has been updated in the past 8 hours: + +```json +mutation createVolumeAssertion { + createVolumeAssertion( + input: { + entityUrn: "", + type: ROW_COUNT_TOTAL, + rowCountTotal: { + operator: BETWEEN, + parameters: { + minValue: { + "value": 10, + "type": NUMBER + }, + maxValue: { + "value": 20, + "type": NUMBER + } + } + } + } + ) { + urn +} +} +``` + +To create an assertion that specifies that the row count total should always fall between 10 and 20. + +The supported volume assertion types are `ROW_COUNT_TOTAL` and `ROW_COUNT_CHANGE`. Other (e.g. incrementing segment) types are not yet supported. +The supported operator types are `GREATER_THAN`, `GREATER_THAN_OR_EQUAL_TO`, `LESS_THAN`, `LESS_THAN_OR_EQUAL_TO`, and `BETWEEN` (requires minValue, maxValue). +The supported parameter types are `NUMBER`. + +To create an Assertion Monitor Entity that evaluates the volume assertion every 8 hours using the Information Schema: + +```json +mutation createAssertionMonitor { + createAssertionMonitor( + input: { + entityUrn: "", + assertionUrn: "", + schedule: { + cron: "0 */8 * * *", + timezone: "America/Los_Angeles" + }, + parameters: { + type: DATASET_VOLUME, + datasetVolumeParameters: { + sourceType: INFORMATION_SCHEMA, + } + } + } + ) { + urn + } +} +``` + +This entity defines _when_ to run the check (Using CRON format - every 8th hour) and _how_ to run the check (using the Information Schema). + +After creating the monitor, the new assertion will start to be evaluated every 8 hours in your selected timezone. + +You can delete assertions along with their monitors using GraphQL mutations: `deleteAssertion` and `deleteMonitor`. + +### Tips + +:::info +**Authorization** + +Remember to always provide a DataHub Personal Access Token when calling the GraphQL API. To do so, just add the 'Authorization' header as follows: + +``` +Authorization: Bearer +``` + +**Exploring GraphQL API** + +Also, remember that you can play with an interactive version of the Acryl GraphQL API at `https://your-account-id.acryl.io/api/graphiql` +::: diff --git a/docs/managed-datahub/operator-guide/setting-up-remote-ingestion-executor-on-aws.md b/docs/managed-datahub/operator-guide/setting-up-remote-ingestion-executor-on-aws.md index d389ec97d05502..b8fb0ea9e80f17 100644 --- a/docs/managed-datahub/operator-guide/setting-up-remote-ingestion-executor-on-aws.md +++ b/docs/managed-datahub/operator-guide/setting-up-remote-ingestion-executor-on-aws.md @@ -17,11 +17,19 @@ Acryl DataHub comes packaged with an Acryl-managed ingestion executor, which is For example, if an ingestion source is not publicly accessible via the internet, e.g. hosted privately within a specific AWS account, then the Acryl executor will be unable to extract metadata from it. -![Option 1: Acryl-hosted ingestion runner](../imgs/saas/image-(12).png) + +

+ +

+ To accommodate these cases, Acryl supports configuring a remote ingestion executor which can be deployed inside of your AWS account. This setup allows you to continue leveraging the Acryl DataHub console to create, schedule, and run metadata ingestion, all while retaining network and credential isolation. -![Option 2: Customer-hosted ingestion runner](../imgs/saas/image-(6).png) + +

+ +

+ ## Deploying a Remote Ingestion Executor 1. **Provide AWS Account Id**: Provide Acryl Team with the id of the AWS in which the remote executor will be hosted. This will be used to grant access to private Acryl containers and create a unique SQS queue which your remote agent will subscribe to. The account id can be provided to your Acryl representative via Email or [One Time Secret](https://onetimesecret.com/). @@ -40,23 +48,39 @@ To accommodate these cases, Acryl supports configuring a remote ingestion execut Note that the only external secret provider that is currently supported is AWS Secrets Manager. -![](../imgs/saas/Screen-Shot-2023-01-19-at-5.12.47-PM.png) -![](../imgs/saas/Screen-Shot-2023-01-19-at-5.12.56-PM.png) +

+ +

+ + + +

+ +

+ 3. **Test the Executor:** To test your remote executor: 1. Create a new Ingestion Source by clicking '**Create new Source**' the '**Ingestion**' tab of the DataHub console. Configure your Ingestion Recipe as though you were running it from inside of your environment. 2. When working with "secret" fields (passwords, keys, etc), you can refer to any "self-managed" secrets by name: `${SECRET_NAME}:` - ![Using a secret called BQ_DEPLOY_KEY which is managed in AWS secrets manager](../imgs/saas/Screen-Shot-2023-01-19-at-4.16.52-PM.png) + +

+ +

+ 3. In the 'Finish Up' step, click '**Advanced'**. 4. Update the '**Executor Id**' form field to be '**remote**'. This indicates that you'd like to use the remote executor. 5. Click '**Done**'. Now, simple click '**Execute**' to test out the remote executor. If your remote executor is configured properly, you should promptly see the ingestion task state change to 'Running'. -![](../imgs/saas/Screen-Shot-2022-03-07-at-10.23.31-AM.png) + +

+ +

+ ## Updating a Remote Ingestion Executor In order to update the executor, ie. to deploy a new container version, you'll need to update the CloudFormation Stack to re-deploy the CloudFormation template with a new set of parameters. ### Steps - AWS Console @@ -66,7 +90,11 @@ In order to update the executor, ie. to deploy a new container version, you'll n 4. Select **Replace Current Template** 5. Select **Upload a template file** 6. Upload a copy of the Acryl Remote Executor [CloudFormation Template](https://raw.githubusercontent.com/acryldata/datahub-cloudformation/master/Ingestion/templates/python.ecs.template.yaml) -![](../imgs/saas/Screen-Shot-2023-01-19-at-4.23.32-PM.png) + +

+ +

+ 7. Click **Next** 8. Change parameters based on your modifications (e.g. ImageTag, etc) 9. Click **Next** diff --git a/docs/managed-datahub/release-notes/v_0_2_11.md b/docs/managed-datahub/release-notes/v_0_2_11.md new file mode 100644 index 00000000000000..1f420908487127 --- /dev/null +++ b/docs/managed-datahub/release-notes/v_0_2_11.md @@ -0,0 +1,73 @@ +# v0.2.11 +--- + +Release Availability Date +--- +14-Sep-2023 + +Recommended CLI/SDK +--- +- `v0.11.0` with release notes at https://github.com/acryldata/datahub/releases/tag/v0.10.5.5 +- [Deprecation] In LDAP ingestor, the manager_pagination_enabled changed to general pagination_enabled + +If you are using an older CLI/SDK version then please upgrade it. This applies for all CLI/SDK usages, if you are using it through your terminal, github actions, airflow, in python SDK somewhere, Java SKD etc. This is a strong recommendation to upgrade as we keep on pushing fixes in the CLI and it helps us support you better. + +Special Notes +--- +- Deployment process for this release is going to have a downtime when systme will be in a read only mode. A rough estimate 1 hour for every 2.3 million entities (includes soft-deleted entities). + + +## Release Changelog +--- +- Since `v0.2.10` these changes from OSS DataHub https://github.com/datahub-project/datahub/compare/2b0952195b7895df0a2bf92b28e71aac18217781...75252a3d9f6a576904be5a0790d644b9ae2df6ac have been pulled in. +- Misc fixes & features + - Proposals + - Group names shown correctly for proposal Inbox + - Metadata tests + - Deprecate/Un-deprecate actions available in Metadata tests + - Last Observed (in underlying sql) available as a filter in metadata tests + - [Breaking change] Renamed `__lastUpdated` -> `__created` as a filter to correctly represent what it was. This was not surfaced in the UI. But if you were using it then this needs to be renamed. Acryl Customer Success team will keep an eye out to pro-actively find and bring this up if you are affected by this. + - Robustness improvements to metadata test runs + - Copy urn for metadata tests to allow for easier filtering for iteration over metadata test results via our APIs. + - A lot more fixes to subscriptions, notifications and Observability (Beta). + - Some performance improvements to lineage queries + +## Some notable features in this SaaS release +- We now enable you to create and delete pinned announcements on your DataHub homepage! If you have the “Manage Home Page Posts” platform privilege you’ll see a new section in settings called “Home Page Posts” where you can create and delete text posts and link posts that your users see on the home page. +- Improvements to search experience +
+